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 yield
d2 = next(c)
"""
study yield
go on!
Traceback (most recent call last):
File "D:/idea/workspace/pythonSpace/PythonDemo/static/yield_demo.py", line 35, in <module>
d2 = next(c)
StopIteration
"""
  • 1
  • 2
  • 3
  • 4

next()被调用后,h()开始执行,直到遇到yield 5

因此输出结果是:study yield

当我们再次调用next()时,会继续执行,直到找到下一个yield。由于后面没有yield了,因此会拋出异常:

study yield
go 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 yield
Fighting!

注意 生成器刚启动时(第一次调用),请使用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 yield
Fighting!
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.'''
# 用于在生成器中抛出一个异常。
pass def 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的更多相关文章

  1. 理解python yield

    python源代码中经常会有使用yield,带有yield的函数是generator(生成器),它返回是一个迭代值,下面我们分析yield是什么原理,有什么好处? 首先,我们写一个简单的斐波那契数列前 ...

  2. 深入理解Python中的yield和send

    send方法和next方法唯一的区别是在执行send方法会首先把上一次挂起的yield语句的返回值通过参数设定,从而实现与生成器方法的交互. 但是需要注意,在一个生成器对象没有执行next方法之前,由 ...

  3. 彻底理解Python中的yield

    阅读别人的python源码时碰到了这个yield这个关键字,各种搜索终于搞懂了,在此做一下总结: 通常的for…in…循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文 ...

  4. 【Python注意事项】如何理解python中间generator functions和yield表情

    本篇记录自己的笔记Python的generator functions和yield理解表达式. 1. Generator Functions Python支持的generator functions语 ...

  5. 理解Python中的yield

    1.通常的for...in...循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文件.它可以是mylist = [1, 2, 3],也可以是mylist = [x*x ...

  6. 深入理解python中的yield关键字

    想必大家都看过这样的代码: 上面的这段代码会计算0-9的平方并打印出来. 那么问题来了,这段代码和我们要说的东西有什么区别呢? 这里的关键字,yield,我在前面的文章里已经发过了.那么yield是什 ...

  7. Python yield与实现

    Python yield与实现  yield的功能类似于return,但是不同之处在于它返回的是生成器. 生成器 生成器是通过一个或多个yield表达式构成的函数,每一个生成器都是一个迭代器(但是迭 ...

  8. 深入理解 Python 异步编程(上)

    http://python.jobbole.com/88291/ 前言 很多朋友对异步编程都处于"听说很强大"的认知状态.鲜有在生产项目中使用它.而使用它的同学,则大多数都停留在知 ...

  9. 深入理解Python异步编程(上)

    本文代码整理自:深入理解Python异步编程(上) 参考:A Web Crawler With asyncio Coroutines 一.同步阻塞方式 import socket def blocki ...

随机推荐

  1. ClickOnce 和管理员权限

    有些程序需要管理员权限需要运行,同时又想用ClickOnce进行发布,这时候就麻烦了,两者是互斥的. 解决方案是,去掉管理员权限的要求,可以进行发布. 程序启动的时候,加载程序员权限的请求. 代码如下 ...

  2. python-局部变量和全局变量

    name = "feifei" def change_name(name): print("before change name:%s" % name) nam ...

  3. TDate赋值给Variant时注意的问题

    //Delphi 10.3.1 32bit, Win 7 32bit procedure TForm1.btnTimeToVariantClick(Sender: TObject); var d:TD ...

  4. Codex Delphi Expert

    https://www.delphiworlds.com/codex/?tdsourcetag=s_pcqq_aiomsg Codex是什么? 是一个可以安装到Delphi IDE中的专家 有助于提高 ...

  5. Python MRO_C3

    class A: pass class B(A): pass class C(A): pass class D(B, C): pass class E(C, A): pass class F(D, E ...

  6. smali语法详解

    smali文件格式 每个smali文件都由若干条语句组成,所有的语句都遵循着一套语法规则.在smali 文件的头3 行描述了当前类的一些信息,格式如下: .class < 访问权限> [  ...

  7. HDU 6090 17多校5 Rikka with Graph(思维简单题)

    Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he ...

  8. POJ 2369 Permutations(置换群概念题)

    Description We remind that the permutation of some final set is a one-to-one mapping of the set onto ...

  9. 树莓派与node.js —— onoff、dht

    1. 发光二极管 tm-onoff var Gpio = require('tm-onoff').Gpio, led = new Gpio(17, 'out'), button = new Gpio( ...

  10. 3D 网页,webgl ,threejs 实例

    http://learningthreejs.com/blog/2013/04/30/closing-the-gap-between-html-and-webgl/ http://adndevblog ...