迭代,列表生成式,生成器,迭代器

2020-11-09  本文已影响0人  Brucezen

'''可以判断一个对象是否可迭代对象'''
from collections.abc import Iterable
isinstance('abc',Iterable)

'''将一个可迭代对象变成(下标,值)的元素对进行索引'''
for i, value in enumerate('abc'):
    print(i, value)

列表生成式的用法

[x*x for x in range(1,11) if x%2 == 0] #加上if判断

[m+n for m in 'ABC' for n in 'XYZ'] #使用两层循环
Output:['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

d = {'x':'A', 'y':'B', 'z':'C'}
[k + '=' + v for k, v in d.items()] #用两个变量来生成list
Output:['x=A', 'y=B', 'z=C']

L = ['Hello','World','IBM', 'Apple']
[s.lower() for s in L]  #把一个字符串list的元素都变成小写的

'''if...else语句+for循环,记住if...else必须在for前面且此处else不能省略'''
[x if x%2==0 else -x for x in range(1,11)]
Out:[-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]

关于生成器:
列表生成式可以直接创建一个列表。但如果仅需要访问前面几个元素,那后面元素占用的空间就浪费了。
所以,如果列表元素可以按照某种算法推算出来,可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。
在Python中,这种一边循环一边计算的机制,称为生成器:generator。

  1. 创建生成器的第一个方法,把列表生成式的[]变为():
L = [x**x for x in range(10)]
g = (x**2 for x in range(10))
# L是列表,而g是一个生成器
print(type(L),type(g))
out:<class 'list'> <class 'generator'>

#由于generator也是可迭代对象,因此我们可以对它用for循环
for n in g:
    print(n)
  1. 创建生成器的第二个方法,在函数里使用yield
def fib(max):
    n, a, b = 0,0,1
    while n < max:
        print(b)
        a,b = b, a+b
        n += 1
    return 'done'

def g_fib(max):
    n, a, b = 0,0,1
    while n < max:
        yield b
        a,b = b, a+b
        n += 1
    return 'done'
print(type(fib),type(g_fib))
Out:<class 'function'> <class 'function'>

# 可以看到g_f是一个生成器
g_f = g_fib(6)
print(type(g_f))
Out:<class 'generator'>

generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:

# 用for循环调用generator时,发现拿不到函数g_fib()的返回值
for i in g_fib(6):
    print(i)
Out:
1
1
2
3
5
8

'''想要拿到返回值,必须捕获StopIteration错误; 用try... except语句捕获异常StopIteration, 返回值包含在StopIteration的value中'''
g_f = g_fib(6)
while True:
    try:
        x = next(g_f)
        print('g_f:',x)
    except StopIteration as e:
        print('Generator return value:', e.value)
        break
Out:
g_f: 1
g_f: 1
g_f: 2
g_f: 3
g_f: 5
g_f: 8
Generator return value: done

可以直接作用于for循环的数据类型有: list,tuple,dict,set,str和generator(包括生成器和带yield的generator function);这些统称为可迭代对象:Iterable,可以用isinstance()判断一个对象是否Iterable:

from collections.abc import Iterable
isinstance([],Iterable)

生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用isinstance()判断一个对象是否是Iterator对象:

from collections.abc import Iterator
isinstance((x for x in range(10)),Iterator)

生成器都是Iterator对象,但list,dict,str虽然是Iterable,但却不是Iterator.可以用iter()函数把Iterable变成Iterator

from collections.abc import Iterable, Iterator
print(isinstance('abc', Iterator))
print(isinstance(iter('abc'), Iterator))
Out:
False
True
上一篇下一篇

猜你喜欢

热点阅读