1.生成器的定义
在python中,一边循环一边计算的机制,称为生成器:generator
2.为什么要有生成器
列表所有数据都在内存中,如果有海量数据的话将会非常耗内存。如仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。如果列表元素按照某种算法推算出来,那我们就可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。简单一句话:想要的到庞大的数据,又想让它占用空间少,那就用生成器
3.生成器的创建
a.只需要将列表生成器的[]改成()就创建了一个generator
a = [x for x in range(10)] b = (x for x in range(10)) print("a的类型为:",type(a)) print("b的类型为:",type(b)) #generator的调用方式 #第一种方式 print(b.__next__()) #第二种方式 print(next(b)) b.一个函数中包含yield关键字,那么这个函数就不再是一个普通的函数,而是一个generator。调用函数就是创建了一个生成器对象
def fib(max): n, a, b = 0, 0, 1 while n < max: a, b = b, a + b n = n + 1 print(a) return 'done' a = fib(10) print(fib(10))
4.生成器的工作原理
a.生成器能够迭代的关键是它有一个next()方法,工作原理就是通过重复调用next()方法,直到捕获一个异常
b.带有yield的函数不在是一个普通的函数,而是一个生成器generator。可用next()调用生成器对象来取值。next()两种方式t.__next__() | next(t)
c.yield相当于return返回一个值,并且记住这个返回的位置,下次迭代的时候,代码从yield的下一条语句开始执行
d. .send()和next()一样,都能让生成器继续往下走一步,但send()能传一个值,这个值作为yield表达式整体的结果
解析:换句话说,就是send可以强行修改上一个yield表达式值,比如函数中有一个yield赋值,a=yield 5,第一次迭代到这里会返回5,a还没有赋值。第二次迭代时,使用.send(10),那么,就是强行修改yield 5表达式的值为10,本来是5的,那么a=10
eg:
#encoding:UTF-8 def yield_test(n): for i in range(n): yield call(i) print("i=",i) print("Done.") def call(i): return i*2 for i in yield_test(5): print(i,",")
def count_down(n):
while n >= 0:
newn = yield n
print('newn', newn)
if newn:
print('if')
n = newn
print('n =', n)
else:
n -= 1
cd = count_down(5)
for i in cd:
print(i, ',')
if i == 5:
cd.send(3)