深入理解 Python yield,,https://bl
深入理解 Python yield,,https://bl
https://blog.csdn.net/lftaoyuan/article/details/78915518
python2和python3是不兼容的,通篇环境都是python3.6
简单的yield实例
以前只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子:
def addlist(alist): for i in alist: yield i + 1
取出alist的每一项,然后把i + 1塞进去。然后通过调用取出每一项:
alist = [1, 2, 3, 4]for x in addlist(alist): print(x)
这的确是yield应用的一个例子,但是,看过很多东西,并自己反复体验后,对yield有了一个全新的理解,其中这篇算是精品了。
包含yield的函数
假如你看到某个函数包含了yield,这意味着这个函数已经是一个Generator,它的执行会和其他普通的函数有很多不同。比如下面的简单的函数:
def h(): print(‘study yield‘) yield 5 print(‘go on!‘)h()
可以看到,调用h()之后,print 语句并没有执行!这就是yield。具体的内容后面会越来越清晰,包括yield的工作原理。
yield是一个表达式
python 2.5以前,yield是一个语句,我也没有考证,因为早都不用了,现在yield是一个表达式:
m = yield 5
表达式(yield 5)的返回值将赋值给m,所以,m = 5肯定是错的。
那么如何获取(yield 5)的返回值呢?需要用到send(msg)。
yield工作原理
揭晓yield的工作原理,需要配合next()函数。上面的h()被调用后并没有执行,因为它有yield表达式,通过next()可以恢复Generator执行,直到下一个yield。
def h(): print(‘study yield‘) yield 5 print(‘go on!‘)c = h()d1 = next(c) # study yieldd2 = next(c)"""study yieldgo on!Traceback (most recent call last): File "D:/idea/workspace/pythonSpace/PythonDemo/static/yield_demo.py", line 35, in <module> d2 = next(c)StopIteration"""
1234next()被调用后,h()开始执行,直到遇到yield 5
因此输出结果是:study yield
当我们再次调用next()时,会继续执行,直到找到下一个yield。由于后面没有yield了,因此会拋出异常:
study yieldgo on!Traceback (most recent call last): File "D:/idea/workspace/pythonSpace/PythonDemo/static/yield_demo.py", line 35, in <module> d2 = next(c)StopIteration
send(msg) 与 next()
了解了next()如何让包含yield的函数执行后,我们再来看另外一个非常重要的函数send(msg)。
其实next()和send()在一定意义上作用是相似的
区别
send()可以传递yield的值
next()只能传递None。
所以next()和send(None)作用是一样的。
def s(): print(‘study yield‘) m = yield 5 print(m) d = yield 16 print(‘go on!‘)c = s()s_d = next(c) # 相当于send(None)c.send(‘Fighting!‘) # (yield 5)表达式被赋予了‘Fighting!‘
输出的结果为:
study yieldFighting!
注意生成器刚启动时(第一次调用),请使用next()语句或是send(None),不能直接发送一个非None的值,否则会报TypeError,因为没有yield语句来接收这个值。
send(msg) 与 next()的返回值
send(msg)和next()的返回值比较特殊,是下一个yield表达式的参数(yield 5,则返回 5)。
到这里,第一个例子中,通过for i in alist遍历Generator,其实是每次都调用了next(),而每次next()的返回值正是yield的参数:
def s(): print(‘study yield‘) m = yield 5 print(m) d = yield 16 print(‘go on!‘)c = s()s_d1 = next(c) # 相当于send(None)s_d2 = c.send(‘Fighting!‘) # (yield 5)表达式被赋予了‘Fighting!‘print(‘My Birth Day:‘, s_d1, ‘.‘, s_d2)
输出结果:
study yieldFighting!My Birth Day: 5 . 16
中断Generator
上面的例子中,当没有可执行程序的时候,会抛出一个StopIteration, 开发过程中,中断Generator是一个非常灵活的技巧
throw
通过抛出一个GeneratorExit异常来终止Generator。
close
close的作用和throw是一样的,看它的源码,可以发现,它和raise一球样
def throw(self, type, value=None, traceback=None): ‘‘‘Used to raise an exception inside the generator.‘‘‘ # 用于在生成器中抛出一个异常。 passdef close(self): ‘‘‘Raises new GeneratorExit exception inside the generator to terminate the iteration.‘‘‘ # 在生成器中生成新的GeneratorExit异常来终止迭代。 pass
其实最后一个中断生成器可以忽略的,在开发过程中,不可避免的要用到这些,但是Python3内部已经做得很好了,一般不太需要手动去做这件事情。
demo地址
https://github.com/seeways/PythonDemo/blob/master/static/yield_demo.py
深入理解 Python yield
相关内容
- Python标准库:内置函数len(s),,本函数是返回对象s的
- python模拟登录http请求中的Accept-Language,,Accept-Lan
- Python第三方库paramiko SSH连接,,基于用户名和密码的s
- python3.5过滤网址和图片的函数自己亲测可用,,def has_
- python + flask轻量级框架,,fromflaski
- python 函数定义和调用,,一、python 函
- python多进程共享内存,,from multi
- python远程下载,,class SFTP
- 一道Python面试题:给出d = [True, False, True, False, True],请
- python骚操作---Print函数用法,,---恢复内容开始-
评论关闭