2021年2月22日 / 6次阅读 / Last Modified 2021年2月22日
python有一个生成器概念,代码每当执行到yield的时候,函数就返回,并且python解释器记住了yield这一行的位置,下次还能从这一行后面开始继续执行。这种特性恐怕只有解释性的语言才有。(专业术语叫挂起,唤醒)
这是之前的一篇生成器blog。生成器跟python的coroutine(协程)的实现有关,本文先总结生成器的一些其它基础特性。
>>> def test():
... for i in ran
... yield i
...
>>>
>>> f = test()
>>> next(f)
0
>>> next(f)
1
>>> next(f)
2
>>> next(f)
3
>>> g = test()
>>> g.send(None)
0
>>> g.send(None)
1
>>> g.send(None)
2
>>> g.send(None)
3
不仅能用next调用生成器,生成器还自带一个send函数,效果与next似乎一样,触发生成器的执行,并停留在yield那一行。
send函数是什么意思?它可以向已经开始执行的生成器内部传一个参数,看如下代码:
>>> def test2():
... for i in range
... j = yield i
... print('j = ',j)
...
>>> f = test2()
>>> next(f)
0
>>> next(f)
j = None
1
>>> next(f)
j = None
2
>>> next(f)
j = None
3
>>> g = test2()
>>> g.send(None)
0
>>> g.send('123')
j = 123
1
>>> g.send('1234')
j = 1234
2
>>> g.send('12345')
j = 12345
3
>>> h = test2()
>>> next(h)
0
>>> h.send('666')
j = 666
1
>>>
yield i变成了赋值语句的一部分,它除了保持原语义之外,还成了能够接收send函数传入参数的方式。从上面代码能够看出,可以用next或者send(None)启动生成器,然后send函数就开发发挥传入参数的威力了!
close函数停止生成器。
>>> def test3():
... for i in range(4):
... try:
... yield i
... except Exception as e:
... print(repr(e))
...
>>> f = test3()
>>> next(f)
0
>>> next(f)
1
>>> f.close()
>>> next(f)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
调用生成器的close函数后,就不能再执行了,会抛出StopIteration异常。我看到有些资料上说,生成器内部在close的时候,会有GeneratorExit一行,但以上代码没有捕获到。
throw函数,向生成器内扔异常
还是上面的test3函数,我们换一种方式来执行:
>>> g = test3()
>>> next(g)
0
>>> next(g)
1
>>> g.throw(ValueError('abcde'))
ValueError('abcde')
2
>>> g.throw(ValueError('12345'))
ValueError('12345')
3
>>> g.throw(IndexError('abcde12345'))
IndexError('abcde12345')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
调用throw函数,可以向生成器内扔异常,但是注意,它同样也在触发生成器的新一轮的执行!
以上就是python生产等对象的3个有趣的方法,send,close,throw。
生成器可以嵌套,还有一个yield from语句:
def reader():
# 模拟从文件读取数据的生成器,for表达式可以简写为:yield from range(4)
#for i in range(4):
# yield i
yield from range(4)
def reader_wrapper():
yield from reader()
wrap = reader_wrapper()
for i in wrap:
print(i)
-- EOF --
本文链接:https://www.pynote.net/archives/3544
《再说generator生成器》有1条留言
Ctrl+D 收藏本页
©Copyright 麦新杰 Since 2019 Python笔记
yield 在这里就像一扇门,可以把一件东西从这里送出去,也可以把另一件东西拿进来。 [ ]