Python: generator, yield, yield from 详解
1.Generator Expressions
生成器表达式是用小括号表示的简单生成器标记法:
generator_expression ::= "(" expression comp_for ")"
生成器表达式产生一个生成器对象,它的语法和for类似,出了它是被“()”包含,而不是[]或{};
生成器表达式中变量的计算被延迟到__next__()函数的调用,然而最左边for循环子句被立即计算,这样,如果他有错误的话可以被立即看到。后面的for循环子句不能被立即计算,因为他们可能依赖于前面的for循环,例如(x*y for x in range(10) for y in bar(x))
python3.6以后,如果生成器出现在async def function中,那么async for子句和await表达式可以被理解为是异步的。如果生成器表达式包含async for子句或者await表达式,就叫做异步生成器表达式。异步生成器表达式产生一个新的异步生成器对象,它是一个异步迭代器。
2. Yield Expressions
yield_atom ::= "("yield_expression
")"
yield_expression ::= "yield" [expression_list
| "from"expression
] Yield表达式用于定义一个生成器函数或异步生成器函数,因此只能被用于一个函数定义体内。在一个函数定义体中使用yield表达式使其成为生成器,
在一个async def函数体内使用yield表达式使协程函数成为一个异步生成器。例如:
def gen(): //定义一个生成器函数
yield 123
async def agen(): //定义一个异步生成器函数
yield 123 当一个生成器函数被调用,它返回一个迭代器,也叫生成器。这个生成器控制生成器函数的执行。当生成器的一个函数被调用的时候,生成器函数开始执行。
执行到第一个yield表达式时,挂起,返回expression_list的值给调用者。对于挂起,我们指的是所有局部状态被保留,包含当前局部变量的绑定,
指令指针,内部调用栈,任何异常处理状态。当通过调用生成器的一个函数恢复执行时,函数的执行就好像是从外部再次调用yield表达式一样。恢复执行后,
yield表达式的值取决调用的方法。如果是__next__()被调用(一般通过for循环或者内置的next()函数),那么值是None。如果是send()被调用,
值是传给send的参数的值。 所有的这些使得生成器函数非常像协程;它产生多次值,有多个入口点并且执行可以被挂起。唯一的不同是,生成器函数yield后不能控制程序从哪里继续执行,
控制权总是传回给生成器的调用者。 yield表达式可以在try块的任何地方,如果生成器在被结束(到达零引用或者因为垃圾回收机制)之前没有被恢复执行,生成器的close函数被调用,因此finally
子句被执行。
当yield from <expr> 被使用,它把附加的表达式当成一个子迭代器,所有子迭代器产生的值被直接传回给当前生成器函数的调用者。当前生成器调用send的参数值
和调用throw的异常参数 都将被传给底层迭代器(子迭代器),如果他有对应的方法的话。否则,send导致AttributeError或者TypeError,而throw立即
raise传给他的异常。
当底层迭代器执行完成,StopIteration对象的value值变成这个yield from表达式的值。这个值可以被显式的设置当产生StopIteration时,或者自动设置,如果
子迭代器是一个生成器(子生成器返回一个值)
3. 生成器-迭代器 方法
这部分介绍生成器迭代器的方法,他们可以被用来控制生成器函数的执行。当生成器正在执行时调用这些函数将导致ValueError。
(1)generator.__next__()
开始生成器函数的执行或者从最后被执行的yield表达式中恢复执行,如果是恢复执行,yield表达式的值是None,继续执行到下一个yield表达式,
挂起,返回expression_list的值给__next__()的调用者。如果生成器没有再yield一个值,则产生一个StopIteration异常
这个方法一般被隐式调用,例如for循环,next()
(2)generator.send(value)
恢复执行并且发送一个值到生成器函数。这个value参数就是当前yield表达式的结果。send方法返回下一个生成器yield的值
如果没有yield,返回StopIteration。当用send来启动生成器,他的参数必须是None,因为没有yield表达式接收值。
(3)generator.throw(type[,value[,traceback]])
在生成器挂起的地方产生一个type类型的异常,并且返回下一个生成器函数yield的值,如果没有yield,返回StopIteration。
如果生成器函数没有捕获这个传进去的异常 ,或者产生了另一个不同的异常,那么将这个异常传递给调用者。
(4)generator.close()
在生成器挂起的地方产生一个GeneratorExit(),如果生成器之后优雅的退出,已经关闭,或者产生了一个GeneartorExit(不捕获该异常),close将返回到它的
调用者。如果生成器yield一个值,那么产生一个RuntimeError。如果生成器产生了任何其他异常,将传递给调用者。如果
生成器因为一个异常或者正常退出,那么close不做任何事情。
实例:
>>> def echo(value=None):
... print("Execution starts when 'next()' is called for the first time.")
... try:
... while True:
... try:
... value = (yield value)
... except Exception as e:
... value = e
... finally:
... print("Don't forget to clean up when 'close()' is called.")
...
>>> generator = echo(1)
>>> print(next(generator))
Execution starts when 'next()' is called for the first time.
1
>>> print(next(generator))
None
>>> print(generator.send(2))
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called. PEP380 加入了yield from表达式,允许一个生成器委派部分操作给另一个生成器。这可以剔除一部分包含yield的代码放到另一个生成器。另外,
子生成器可以返回一个值,这个值对于委托生成器也是可用的。
虽然主要涉及用来委派一个子生成器,但是yield from 表达式事实上可以委派任何的子迭代器。
低于简单的迭代器, yield from iterable 本质上就是一个简短的形式:for item in iterable: yield item,例如:
>>> def g(x):
... yield from range(x, 0, -1)
... yield from range(x)
...
>>> list(g(5))
[5, 4, 3, 2, 1, 0, 1, 2, 3, 4]
然而,不像普通的循环,yield from 允许子生成器直接从调用区域接收send和throw的值,并且返回一个最后的值给外层生成器。示例如下:
>>> def accumulate():
... tally = 0
... while 1:
... next = yield
... if next is None:
... return tally
... tally += next
...
>>> def gather_tallies(tallies):
... while 1:
... tally = yield from accumulate()
... tallies.append(tally)
...
>>> tallies = []
>>> acc = gather_tallies(tallies)
>>> next(acc) # Ensure the accumulator is ready to accept values
>>> for i in range(4):
... acc.send(i)
...
>>> acc.send(None) # Finish the first tally
>>> for i in range(5):
... acc.send(i)
...
>>> acc.send(None) # Finish the second tally
>>> tallies
[6, 10]
Python: generator, yield, yield from 详解的更多相关文章
- Python Deque 模块使用详解,python中yield的用法详解
Deque模块是Python标准库collections中的一项. 它提供了两端都可以操作的序列, 这意味着, 你可以在序列前后都执行添加或删除. https://blog.csdn.net/qq_3 ...
- [转]使用python来操作redis用法详解
转自:使用python来操作redis用法详解 class CommRedisBase(): def __init__(self): REDIS_CONF = {} connection_pool = ...
- Python安装、配置图文详解(转载)
Python安装.配置图文详解 目录: 一. Python简介 二. 安装python 1. 在windows下安装 2. 在Linux下安装 三. 在windows下配置python集成开发环境(I ...
- 【和我一起学python吧】Python安装、配置图文详解
Python安装.配置图文详解 目录: 一. Python简介 二. 安装python 1. 在windows下安装 2. 在Linux下安装 三. 在windows下配置python集成开发环境( ...
- Python中的高级数据结构详解
这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考 ...
- Python中格式化format()方法详解
Python中格式化format()方法详解 Python中格式化输出字符串使用format()函数, 字符串即类, 可以使用方法; Python是完全面向对象的语言, 任何东西都是对象; 字符串的参 ...
- python设计模式之装饰器详解(三)
python的装饰器使用是python语言一个非常重要的部分,装饰器是程序设计模式中装饰模式的具体化,python提供了特殊的语法糖可以非常方便的实现装饰模式. 系列文章 python设计模式之单例模 ...
- Python调用windows下DLL详解
Python调用windows下DLL详解 - ctypes库的使用 2014年09月05日 16:05:44 阅读数:6942 在python中某些时候需要C做效率上的补充,在实际应用中,需要做部分 ...
- Python操作redis字符串(String)详解 (三)
# -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1.SET 命令用于设置 ...
- 【Python】Python内置函数dir详解
1.命令介绍 最近学习并使用了一个python的内置函数dir,首先help一下: 复制代码代码如下: >>> help(dir)Help on built-in function ...
随机推荐
- object-c 框架之经常使用结构体
Foundation 框架定义经常使用结构体.结构体採用object-c 定义:经常使用NSSRange,NSPoint.NSSize,NSRect等 一.NSRange 创建范围结构体. 方法:NS ...
- linux服务器性能检测工具nmon使用
今天介绍一款linux系统服务器性能检测的工具-nmon及nmon_analyser (生成性能报告的免费工具),亲测可用. 一.介绍 nmon 工具可以帮助在一个屏幕上显示所有重要的性能优化信息,并 ...
- P-Called-Party-ID 头域的应用说明
P-Called-Party-ID 头域的适用场景 P-Called-Party-ID 适用于 UAS 须要知道在代理将目标改写为Contact 地址之前请求中Request-URI的目的AOR的情况 ...
- 【Excle】8个快捷键
1.CtrL+ F1 一键切换功能区是否显示,几乎每天都要用N次. 2.Ctrl + N 一键插入新的工作簿,再不用通过新建 - 空白工作簿来操作了. 3.Shift + F2 如果单元格中没有批注会 ...
- iOS开发之状态栏隐藏(问题篇)
一.基本应用 相信基本的隐藏办法网上很多,这里只简单说明一下 1⃣️改变全局状态栏 1.在项目的Info.plist文件里设置UIViewControllerBasedStatusBarAppeara ...
- mongoDB 高级查询语法
http://www.cnblogs.com/ITAres/articles/2084794.html本文参考自官方的手册:http://www.mongodb.org/display/DOCS/Ad ...
- static 关键字的使用,静态和非静态类的区别
直接以一个例子说明: using System; using System.Collections.Generic; using System.Diagnostics; using System.IO ...
- Security Testing Basics
Security Testing BasicsSoftware security testing is the process of assessing and testing a system to ...
- css 猫头鹰选择器
除了第一个以外的兄弟选择器.由于看起来像猫头鹰,也叫猫头鹰选择器 .TD-Breadcrumb > li + li:before { padding: 0 5px; color: #ccc; c ...
- Spring事务管理之编程式事务管理
© 版权声明:本文为博主原创文章,转载请注明出处 案例:利用Spring的编程式事务管理模拟转账过程 数据库准备 -- 创建表 CREATE TABLE `account`( `id` INT NOT ...