python基础入门---生成器
生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。
而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,
那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?
这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行
def fib(max): n, a, b = 0, 0, 1 while n < max: #print(b) yield b #只要有它在,这里就不是函数了,是一个生成器了。 把fib函数变成generator了。 a, b = b, a + b # 相当于 t = (b, a + b) t是一个tuple a = t[0] b = t[1] n = n + 1 return '---yyyy----' f=fib(10) print(f.__next__()) print(f.__next__()) print(f.__next__()) print(f.__next__()) print("------") for i in f: print(i)
我们在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。
同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代:
for n in fib(6):
print(n)
但是用for循环调用generator时,发现拿不到generator的return语句的返回值。
如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
#print(b)
yield b #只要有它在,这里就不是函数了,是一个生成器了。 把fib函数变成generator了。
a, b = b, a + b # 相当于 t = (b, a + b) t是一个tuple a = t[0] b = t[1]
n = n + 1
return '---yyyy----'
g= fib(6)
while True:
try:
x = next(g)
print("g:",x)
except StopIteration as e:
print("Generator return value:",e.value)
break
最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。
而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行data = fib(print(data)
print(data.__next__()) print(data.__next__()) print("干点别的事") print(data.__next__()) print(data.__next__()) print(data.__next__()) print(data.__next__()) print(data.__next__()) #输出 <generator object fib at 0x101be02b0> 1
1
干点别的事
2 3 5 8 13

浙公网安备 33010602011771号