https://zhuanlan.zhihu.com/p/32178981?utm_medium=social&utm_source=wechat_session
https://zhuanlan.zhihu.com/p/37257918?utm_medium=social&utm_source=wechat_session
####写在前面g.next()是在python2用的,python3用next(g)
1.当函数含有yield,会被系统默认为是一个生成器
2.执行到yield p, 返回p值以及整个生成器处于暂停的状态,并跳出当前函数,执行到调用返回值p的语句
3.当再次执行到这个含有yield的生成器函数时,会自动立即执行到上次暂停的位置继续执行,也就是从yield p这个语句继续执行
常见:yield一般都在def生成器定义中搭配一些循环语句使用,比如for或者while,以防止运行到生成器末尾跳出生成器函数,就不能再yield了。有时候,为了保证生成器函数永远也不会执行到函数末尾,会用while True: 语句,这样就会保证只要使用next(),这个生成器就会生成一个值,是处理无穷序列的常见方法。
当定义一个函数包含Yield时候,此函数也就成为了一个生成器
input:
def fib(max):
a, b = 1, 1
while a < max:
yield a
a, b = b, a+b
-----------------------------用for循环使用fib迭代
for n in fib(15):
print n
output:
1
1
2
3
5
8
13
----------------------------直接使用fib迭代看看要用next才可以
input:
m = fib(13)
print m#打印生成器
print m.next()#打印生成器的第一个值
print m.next()#打印生成器的第二个值
print m.next()#打印生成器的第三个值
output:
<generator object fib at 0x0563D378>
1
1
2
for语句调用了fib(15)。当max=15时,进入fib()生成器,执行到yield a, 返回a值以及整个生成器暂停的状态,将a值赋给n, 打印出来;因为是for语句循环,所以又回到fib(15)语句,由于是生成器,因此从上次截断的位置开始执行,b值赋给a, a+b值赋给b,又因为是while语句,则继续while循环,yield a值(注意yield a的值是在while后面)循环暂停跳出返回a值及生成器状态,把a值赋给n, 打印n。如此往复,一直循环到15结束。
步骤顺序:::
1.---yield a
2.---暂停(不执行后面)函数也得到了a
3.---for循环于是回到yield a的位置执行下一步a,b=b,a+b(只是执行下一步)
4.---while循环回到yield a
5.---暂停(不执行后面)函数也得到了第二个a
m被赋了fib(13)这个生成器,每一次执行m.next()函数就会打印下一个值。
def generate_square(n):
i = 0
while i < n:
yield i * i
i += 1
result = generate_square(3)
print(result) # <generator object generate_square at 0x000001E482F07BA0>
result.next() # 在3中不适用
next(result) #0
next(result) #1
next(result) #4
next(result) #Traceback (most recent call last):
File "<ipython-input-14-709396a5599b>", line 1, in <module>
next(result)
print(list(result)) # [] 因为用完了
result = generate_square(3)
print(list(result)) # [0,1,4] list方法把它们都列出来~~!!!
list方法把它们都列出来~~!!!
那么此方法好在什么地方?
def generate_square(n):
i = 0
while i < n:
yield i * i
i += 1
result = generate_square(10)
print(list(result))
def generate_square(n):
i = 0
result = []
while i < n:
result.append(i * i)
i += 1
return result
result = generate_square(10)
print(result)
上面两个代码有什么不一样呢(结果一样)
两种方式实现的generate_square函数,一个使用了yield关键字,一个使用了列表保存所有的值并返回列表,两者的区别在什么地方?
对于前一种实现方式,使用了生成器,在调用函数的时候不会一次性生成所有的元素,而是在每次调用 next() 才生成一个元素;而后一种方式,在调用函数的时候就生成了所有元素,相比之下,更耗费内存和CPU。