Python中的yield from语法
来源:互联网 发布:网络监控软件哪个好用 编辑:程序博客网 时间:2024/05/16 15:21
这篇文章主要是翻译stackoverflow上的一篇文章,In practice, what are the main uses for the new “yield from” syntax in Python 3.3? 加上自己的一点删改和想法
首先要注意yield from 提供了一种透明的双向通道从caller
到subgenerator
,即可以发送数据到subgenerator
或者从subgenerator
读取数据
Reading data from a generator using yield from
def reader(): """A generator that fakes a read from a file, socket, etc.""" for i in range(4): yield '<< %s' % idef reader_wrapper(g): # Manually iterate over data produced by reader for v in g: yield vwrap = reader_wrapper(reader())for i in wrap: print(i)# Result<< 0<< 1<< 2<< 3
我们可以使用yield from g
来替换for v in g: yield v
这种方式来重新改写reader_wrapper
def reader_wrapper(g): yield from g
我们可以减少一行代码,而且编码的意图更加清晰。但是yield from
并没有引入新的功能
Sending data to a generator(coroutine) using yield from– Part 1
如果不明白怎么发送数据,可以去看Dave Beazley’s Curious Course on Couroutines 上的slides的24-33页。
如果我们把之前使用yield生成数据的叫做generator,那么使用yield读取数据的叫做coroutine(协程)。coroutine和generator是毫无关系的,不要将这两个概念混淆。generator produce data for iteration, coroutine are consumers of data.另外coroutine和iteration是无关的,即使有时候coroutine会使用yield生成数据,但是这也和iteration是无关的。
先创建一个名叫writer
的coroutine接受data并写入到file, socket等等
def writer(): """A coroutine that writes data *sent* to it to fd, socket, etc.""" while True: w = (yield) print('>> ', w)
接着来考虑如何编写装饰器wrapper发送data给writer
使得发送给装饰器wrapper的data都可以透明地传给writer
def writer_wrapper(coro): # TBD passw = writer()wrap = writer_wrapper(w)wrap.send(None) # "prime" the coroutinefor i in range(4): wrap.send(i)# Expected result>> 0>> 1>> 2>> 3
writer_wrapper
需要接收传给它的数据,并且处理StopIteration
异常。下面是一个可以满足要轻松的writer_wrapper
def writer_wrapper(coro): coro.send(None) # prime the coro while True: try: x = (yield) # Capture the value that's sent coro.send(x) # and pass it to the writer except StopIteration: pass
这样可以节省6行代码,并且可读性更强。
Sending data to a generator(coroutine) using yield from – Part 2 – Exception handling
我们现在考虑的更加复杂,让writer
可以处理异常,当writer
遇到SpamException
时,输出***
class SpamException(Exception): passdef writer(): while True: try: w = (yield) except SpamException: print('***') else: print('>> ', w)
如果不改变writer_wrapper
,我们看看是否满足效果
# writer_wrapper same as abovew = writer()wrap = writer_wrapper(w)wrap.send(None) # "prime" the coroutinefor i in [0, 1, 2, 'spam', 4]: if i == 'spam': wrap.throw(SpamException) else: wrap.send(i)# Expected Result>> 0>> 1>> 2***>> 4# Actual Result>> 0>> 1>> 2Traceback (most recent call last): ... redacted ... File ... in writer_wrapper x = (yield)__main__.SpamException
可以看出来不能处理SpamException
,因为x = (yield)
只是抛出异常并没有处理。下边修改writer_wrapper
,让其处理或者throw该异常到subgenerator
def writer_wrapper(coro): """Works. Manually catches exceptions and throws them""" coro.send(None) # prime the coro while True: try: try: x = (yield) except Exception as e: # This catches the SpamException coro.throw(e) else: coro.send(x) except StopIteration: pass
修改满足了效果:
# Result>> 0>> 1>> 2***>> 4
但是下边的代码同样可以做到:
def writer_wrapper(coro): yield from coro
yield from
透明地把data
或Exception
传给了subgenerator
以上并没有覆盖所有的case。比如当外部的generator关闭会发生什么,subgenerator
return一个值时怎么将return的值传递,yield from
都可以处理所有情况。 All the corner cases that yield from handles transparently is really impressive yield from
其实不太能够反映它的双向的特性,有其他的一些关键字被提议例如delegate
但是因为程序语言增加一个关键字比联合现有的关键字更加麻烦,所以采用了yield from
一定要记住yield from
是caller
和subgenerator
之间的透明双向通道
In summary, it’s best to think yield from
as a transparent two-way channel between the caller
and the subgenerator
.
- Python中的yield from语法
- python yield 与 yield from
- python yield 和 yield from用法总结
- python yield from的使用
- python3中的yield from语句
- python中yield语法学习
- Python中的yield
- python 中的 yield
- Python中的yield
- python 中的yield
- python中的yield
- 学习Python中的yield
- python中的yield
- python中的yield
- 关于Python中的yield
- python 中的yield
- 关于Python中的yield
- 关于Python中的yield
- Xcode工程目录的 folder 和 group的区别(蓝色和黄色文件夹的区别)
- HDU 3422, POJ 1305简单的本原勾股数组
- C++ 如何解决string类型无法比较大小的问题
- linux 打包分割合并,解压文件
- Guava collections -- Immutable Collections
- Python中的yield from语法
- 设计模式之简单工厂设计模式
- 为何Hadoop中的块如此之大
- ASP.NET获取<EmptyDataTemplate></EmptyDataTemplate>模板中的textBox控件值
- java语法基础
- 下载maven JAR包太慢?各种方法解决。不再为此烦恼!
- Java 程序死锁问题原理及解决方案
- 二维树狀数组模板
- LeetCode 217. Contains Duplicate