yield与生成器
def func(n):
for i in range(0, n):
print('func: ', i)
# yield i
f = func(10)
程序执行结果
:
func: 0
func: 1
func: 2
func: 3
func: 4
func: 5
func: 6
func: 7
func: 8
func: 9
当我们把注释去掉后:
def func(n):
for i in range(0, n):
print('func: ', i)
yield i
f = func(10)
程序没有任何输出。
输出此函数:
print(func(10))
得到
<generator object func at 0x0000004B57353A98>
我们得出以下结论:
1、带有yield关键字的函数自动变成生成器
2、生成器被调用时不会立即执行
那么,怎么获得生成器的生成的值呢
使用next函数:
import time
def func(n):
for i in range(0, n):
print('func: ', i)
yield i
f = func(10)
while True:
print(next(f))
time.sleep(1)
程序输出:
func: 0
0
func: 1
1
func: 2
2
func: 3
3
func: 4
4
func: 5
5
func: 6
6
func: 7
7
func: 8
8
func: 9
9
Traceback (most recent call last):
File "C:/Users/mingC/PycharmProjects/pro_test/Demo/Demo4.py", line 9, in <module>
print(next(f))
StopIteration
1、对于生成器,当调用函数next(generator)时,将获得生成器yield后面表达式的值;
2、当生成器已经执行完毕时,再次调用next函数,生成器会抛出StopIteration异常
扩展:
1、当生成器内部执行到return语句时,自动抛出StopIteration异常,return的值将作为异常的解释
2、外部可以通过generator.close()函数手动关闭生成器,此后调用next或者send方法将抛出异常
next与send函数
next函数与send函数很相似,都能获得生成器的下一个yield后面表达式的值,不同的是
send函数可以向生成器传参:
import time
def func(n):
for i in range(0, n):
arg = yield i
print('func:', arg)
f = func(10)
while True:
print('main:', next(f))
print('main:', f.send(100))
time.sleep(1)
输出结果:
main: 0
func: 100
main: 1
func: None
main: 2
func: 100
main: 3
func: None
main: 4
func: 100
main: 5
func: None
main: 6
func: 100
main: 7
func: None
main: 8
func: 100
main: 9
Traceback (most recent call last):
func: None
File "C:/Users/mingC/PycharmProjects/pro_test/Demo/Demo4.py", line 9, in <module>
print('main:', next(f))
StopIteration
生成器从第四行继续执行,
send函数的参数100作为yield的返回值,并赋值给arg,然后得到func:100的输出。
简单的说,send函数使得yield关键字拥有了返回值返回给它的左值。
常见错误
import time
def func(n):
for i in range(0, n):
arg = yield i
print('func:', arg)
f = func(10)
while True:
print('main:', f.send(100))
time.sleep(1)
输出:
Traceback (most recent call last):
File "C:/Users/mingC/PycharmProjects/pro_test/Demo/Demo4.py", line 9, in <module>
print('main:', f.send(100))
TypeError: can't send non-None value to a just-started generator
错误说明显示:
不能将一个非None的值传给初始的生成器。
从上面的测试,我们知道,当调用send函数前,生成器内部应该执行到yield所在的语句并暂停。而在这次的测试中,我们从一开始就调用send并传了一个参数,
程序报错误。
因此,在调用带非空参数的send函数之前,我们应该
使用next(generator)或者send(None)使得生成器执行到yield语句并暂停。
import time
def func(n):
for i in range(0, n):
arg = yield i
print('func:', arg)
f = func(5)
print('main:', f.send(None))
while True:
print('main:', f.send(100))
time.sleep(1)
输出结果:
main: 0
func: 100
main: 1
func: 100
main: 2
func: 100
main: 3
func: 100
main: 4
func: 100
Traceback (most recent call last):
File "C:/Users/mingC/PycharmProjects/pro_test/Demo/Demo4.py", line 10, in <module>
print('main:', f.send(100))
StopIteration
关于yield from
yield from 用于生成器的嵌套。详细解释可以看这篇博文:http://blog.theerrorlog.com/yield-from-in-python-3.html
这是我写的第一篇博文,虽然知识点不多,但是也是对自己学习的一个小总结,希望以后能够坚持将自己编程路上的所思所想写到这里,感谢认真观看这篇博文的朋友们。