生成器的语法
生成器表达式: 通列表解析语法,只不过把列表解析的[]换成()
生成器表达式能做的事情列表解析基本都
能处理,只不过在需要处理的序列比较大时,列表解析比较费内存。
1 >>> gen = (x**2 for x in range(5)) 2 >>> gen 3 <generator object <genexpr> at 0x0000000002FB7B40> 4 >>> for g in gen: 5 ... print(g, end='-') 6 ... 7 0-1-4-9-16- 8 >>> for x in [0,1,2,3,4,5]: 9 ... print(x, end='-') 10 ... 11 0-1-2-3-4-5-
生成器函数: 在函数中如果出现了yield关键字,那么该函数就不再是普通函数,而是生成器函数。
一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。
每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
但是生成器函数可以生产一个无线的序列,这样列表根本没有办法进行处理。
yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator。
下面为一个可以无穷生产奇数的生成器函数。
1 def odd(): 2 n=1 3 while True: 4 yield n 5 n+=2 6 odd_num = odd() 7 count = 0 8 for o in odd_num: 9 if count >=5: break 10 print(o) 11 count +=1
生成器是包含有__iter__()和__next__()方法的,所以可以直接使用for来迭代,而没有包含StopIteration的自编Iter来只能通过手动循环来迭代。
在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,
代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,
直到再次遇到 yield。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
1 def func(): 2 a=1 3 print('12315456') 4 yield a 5 print('adsfsdf') 6 b=2 7 yield b 8 print('asdf') 9 yield '123' 10 ret=func() 11 print(next(ret)) 12 print(next(ret)) 13 print(next(ret))