Pet*_*erE 21 python iterable python-3.x yield-from
在包装(内部)迭代器时,通常必须将__iter__方法重新路由到底层的iterable.请考虑以下示例:
class FancyNewClass(collections.Iterable):
def __init__(self):
self._internal_iterable = [1,2,3,4,5]
# ...
# variant A
def __iter__(self):
return iter(self._internal_iterable)
# variant B
def __iter__(self):
yield from self._internal_iterable
Run Code Online (Sandbox Code Playgroud)
变体A和B之间是否有任何显着差异?Variant A返回iter()已从内部iterable中查询过的迭代器对象.变量B返回一个生成器对象,该对象返回内部可迭代的值.出于某种原因,是其中一种还是其他的?在collections.abc该yield from版本中使用.该return iter()变种是,我已经使用到现在的格局.
eca*_*mur 15
唯一显着的区别是当从迭代中引发异常时会发生什么.使用return iter()你的FancyNewClass意志不会出现在异常回溯上,而yield from它会出现.虽然可能存在要隐藏包装器的情况,但尽可能多地获取有关回溯的信息通常是件好事.
其他差异:
return iter必须iter从全局变量中加载名称- 这可能很慢(虽然不太可能显着影响性能)并且可能会被搞乱(尽管任何覆盖像这样的全局变量的人都应该得到它们).
随着yield from您可以插入其他的yield之前和之后的表达式(虽然你同样可以使用itertools.chain).
如上所述,yield from表单会丢弃任何生成器返回值(即raise StopException(value),您可以通过编写来修复此问题return (yield from iterator).
这是一个测试,比较两种方法的反汇编,并显示异常追溯:http://ideone.com/1YVcSe
使用return iter():
3 0 LOAD_GLOBAL 0 (iter)
3 LOAD_FAST 0 (it)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 RETURN_VALUE
Traceback (most recent call last):
File "./prog.py", line 12, in test
File "./prog.py", line 10, in i
RuntimeError
Run Code Online (Sandbox Code Playgroud)
使用return (yield from):
5 0 LOAD_FAST 0 (it)
3 GET_ITER
4 LOAD_CONST 0 (None)
7 YIELD_FROM
8 RETURN_VALUE
Traceback (most recent call last):
File "./prog.py", line 12, in test
File "./prog.py", line 5, in bar
File "./prog.py", line 10, in i
RuntimeError
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1124 次 |
| 最近记录: |