深入理解 Python yield
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的更多相关文章
- 理解python yield
python源代码中经常会有使用yield,带有yield的函数是generator(生成器),它返回是一个迭代值,下面我们分析yield是什么原理,有什么好处? 首先,我们写一个简单的斐波那契数列前 ...
- 深入理解Python中的yield和send
send方法和next方法唯一的区别是在执行send方法会首先把上一次挂起的yield语句的返回值通过参数设定,从而实现与生成器方法的交互. 但是需要注意,在一个生成器对象没有执行next方法之前,由 ...
- 彻底理解Python中的yield
阅读别人的python源码时碰到了这个yield这个关键字,各种搜索终于搞懂了,在此做一下总结: 通常的for…in…循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文 ...
- 【Python注意事项】如何理解python中间generator functions和yield表情
本篇记录自己的笔记Python的generator functions和yield理解表达式. 1. Generator Functions Python支持的generator functions语 ...
- 理解Python中的yield
1.通常的for...in...循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文件.它可以是mylist = [1, 2, 3],也可以是mylist = [x*x ...
- 深入理解python中的yield关键字
想必大家都看过这样的代码: 上面的这段代码会计算0-9的平方并打印出来. 那么问题来了,这段代码和我们要说的东西有什么区别呢? 这里的关键字,yield,我在前面的文章里已经发过了.那么yield是什 ...
- Python yield与实现
Python yield与实现 yield的功能类似于return,但是不同之处在于它返回的是生成器. 生成器 生成器是通过一个或多个yield表达式构成的函数,每一个生成器都是一个迭代器(但是迭 ...
- 深入理解 Python 异步编程(上)
http://python.jobbole.com/88291/ 前言 很多朋友对异步编程都处于"听说很强大"的认知状态.鲜有在生产项目中使用它.而使用它的同学,则大多数都停留在知 ...
- 深入理解Python异步编程(上)
本文代码整理自:深入理解Python异步编程(上) 参考:A Web Crawler With asyncio Coroutines 一.同步阻塞方式 import socket def blocki ...
随机推荐
- unity3d优化总结篇(二)
1. 尽量避免每帧处理,可以每隔几帧处理一次 比如: [C#] 纯文本查看 复制代码 function Update() { DoSomeThing(); } 可改为每5帧处理一次: [C#] ...
- 爬虫框架存储pymysql方式
爬虫框架存储pymysql方式# -*- coding: utf-8 -*-import pymysql# Define your item pipelines here## Don't forget ...
- 使用golang编写prometheus metrics exporter
metrcis输出 collector.go package main import ( "github.com/prometheus/client_golang/prometheus&qu ...
- PAT乙级 1031. 查验身份证(15)
题目传送:https://www.patest.cn/contests/pat-b-practise/1031 一个合法的身份证号码由17位地区.日期编号和顺序编号加1位校验码组成.校验码的计算规则如 ...
- 性能测试-12.Web页面性能指标与建议
1.页面加载时间 从页面开始加载到页面onload事件触发的时间.一般来说onload触发代表着直接通过HTML引用的CSS,JS,图片资源已经完全加载完毕. 2.全部页面加载时间 全部页面载入时间指 ...
- 神州数码RIP协议认证
实验要求:掌握RIP协议的简单认证及MD5认证 拓扑如下 简单认证 R1 enable 进入特权模式 config 进入全局模式 hostname R1 修改名称 interface s0/1 进入 ...
- Python学习笔记第三周
目录 一.基础概念 1.集合 集合方法 a.设置集合 b.取交集 c.取并集 d.取差集 e.判断子集 f.判断父集 g.对称差集 基本操作: a.添加 b.删除 c.discard删除 d.长度 e ...
- Android 1.5-7.0(持续更新)安全机制一览
Android 1.5 ProPolice to prevent stack buffer overruns (-fstack-protector),在缓冲区buffer与返回地址之间加入Canary ...
- Java基础(2)面向对象和封装,对象的创建和使用、java对象的内存图
1 类和对象 类:是一类事物的描述,抽象的.猫 对象:是一类事物的实例,具体的.某只猫 2 类的定义 成员变量和成员方法 //定义一个学生类 public class Student { //成员变量 ...
- 用conda创建python虚拟环境
1.首先在所在系统中安装Anaconda.可以打开命令行输入conda -V检验是否安装以及当前conda的版本. 2.conda常用的命令. 1)conda list 查看安装了哪些包. 2)con ...