“从迭代中获得”vs“返回iter(可迭代)”

时间:2015-05-12 10:03:43

标签: python python-3.x iterable yield-from

当包装(内部)迭代器时,通常必须将public function __construct(\Illuminate\Foundation\Application $app) { $app['_foo'] = 'bar'; } 方法重新路由到底层迭代器。请考虑以下示例:

__iter__

变体A和B之间是否有任何显着差异? Variant A返回一个迭代器对象,该对象已通过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 从内部迭代中查询。变量B返回一个生成器对象,该对象返回内部可迭代的值。出于某种原因,是其中一种还是其他的?在iter()中使用collections.abc版本。 yield from变体是我到目前为止使用的模式。

1 个答案:

答案 0 :(得分:13)

唯一重要的区别是当从迭代中引发异常时会发生什么。使用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

使用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