python 生成器_python:生成器使用场景

本文深入探讨了Python生成器的特性,如如何通过send()和throw()方法传递值和异常。通过示例展示了生成器在处理多维列表展开和异常处理中的应用,同时解释了生成器在协程中的作用。此外,还介绍了如何使用next()、send()和throw()来控制生成器的执行流程,以及如何通过close()来终止生成器。
摘要由CSDN通过智能技术生成

StopIteration

send():生成器函数最大的特点是可以接受外部传入的一个变量,并根据变量内容计算结果后返回。这是生成器函数最难理解的地方,也是最重要的地方,实现后面我会讲到的协程就全靠它了。

def gener():

value=0

while True:

receive=yield value

if receive=='e': break

value = 'got: %s' % receive

g=gener()

print(g.send(None))

print(g.send('aaa'))

print(g.send(3))

print(g.send('e'))>>>0

>>>got: aaa

>>>got: 3

Traceback (most recent call last):

File "h.py", line 14, in print(g.send('e'))

StopIteration

执行流程:

通过g.send(None)或者next(g)可以启动生成器函数,并执行到第一个yield语句结束的位置。

此时,执行完了yield语句,但是没有给receive赋值。

yield value会输出初始值0

注意:在启动生成器函数时只能send(None),如果试图输入其它的值都会得到错误提示信息。

通过g.send('aaa'),会传入aaa,并赋值给receive,然后计算出value的值,并回到while头部,执行yield value语句有停止。

此时yield value会输出"got: aaa",然后挂起。

通过g.send(3),会重复第2步,最后输出结果为"got: 3"

当我们g.send('e')时,程序会执行break然后推出循环,最后整个函数执行完毕,所以会得到StopIteration异常。

最后的执行结果如下:

throw():用来向生成器函数送入一个异常,可以结束系统定义的异常,或者自定义的异常。throw()后直接跑出异常并结束程序,或者消耗掉一个yield,或者在没有下一个yield的时候直接进行到程序的结尾。

def gener():

while True:

try:

yield 'normal value'

yield 'normal value 2'

print('here')

except ValueError:

print('we got ValueError here')

except TypeError:

break

g=gener()

print(next(g))

print(g.throw(ValueError))

print(next(g))

print(g.throw(TypeError))>>>normal value

>>>we got ValueError here

>>>normal value

>>>normal value 2

Traceback (most recent call last):

File "h.py", line 15, in print(g.throw(TypeError))

StopIteration

执行流程::

print(next(g)):会输出normal value,并停留在yield 'normal value 2'之前。

由于执行了g.throw(ValueError),所以会跳过所有后续的try语句,也就是说yield 'normal value 2'不会被执行,然后进入到except语句,打印出we got ValueError here。

然后再次进入到while语句部分,消耗一个yield,所以会输出normal value。

print(next(g)),会执行yield 'normal value 2'语句,并停留在执行完该语句后的位置。

g.throw(TypeError):会跳出try语句,从而print('here')不会被执行,然后执行break语句,跳出while循环,然后到达程序结尾,所以跑出StopIteration异常。

下面给出一个综合例子,用来把一个多维列表展开,或者说扁平化多维列表

def flatten(nested):

try:

#如果是字符串,那么手动抛出TypeError。

if isinstance(nested, str):

raise TypeError

for sublist in nested:

for element in flatten(sublist):

print('got:', element)

except TypeError:

yield nested

L=['abc',[1,2,3],2,4,[5,[6,[8,[9]],'def'],7]]

for num in flatten(L):

print(num)

end:

按照鸭子模型理论,生成器就是一种迭代器,可以使用for进行迭代。

第一次执行next(generator)时,会执行完yield语句后程序进行挂起,所有的参数和状态会进行保存。

再一次执行next(generator)时,会从挂起的状态开始往后执行。

在遇到程序的结尾或者遇到StopIteration时,循环结束。

可以通过generator.send(arg)来传入参数,这是协程模型。

可以通过generator.throw(exception)来传入一个异常。throw语句会消耗掉一个yield。

可以通过generator.close()来手动关闭生成器。

next()等价于send(None)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值