python - "yield from iterable"与 "return iter(iterable)"

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

在包装(内部)迭代器时,通常必须将 __iter__ 方法重新路由到底层可迭代对象。考虑以下示例:

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

变体 A 和 B 之间是否存在显着差异? 变体 A 返回一个迭代器对象,该对象已通过 iter() 从内部可迭代对象中查询。变体 B 返回一个生成器对象,该对象从内部可迭代对象中返回值。出于某种原因,其中一个更可取吗?在 collections.abc 中使用了 yield from 版本。 return iter() 变体是我迄今为止使用的模式。

最佳答案

唯一显着的区别是当从可迭代对象中引发异常时会发生什么。使用 return iter() 您的 FancyNewClass 不会出现在异常回溯中,而使用 yield from 会出现。尽管在某些情况下您可能希望隐藏包装器,但尽可能多地获取有关回溯的信息通常是一件好事。

其他区别:

  • return iter 必须从全局加载名称 iter - 这可能很慢(尽管不太可能显着影响性能)并且可能会被弄乱(尽管任何像这样覆盖全局变量的人都应该得到他们所得到的)。

  • 使用 yield from,您可以在前后插入其他 yield 表达式(尽管您同样可以使用 itertools.chain)。

  • 如前所述,yield from 表单会丢弃任何生成器返回值(即 raise StopException(value)。您可以改写 来解决此问题返回(迭代器产生).

这是一个比较两种方法的反汇编并显示异常回溯的测试: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

关于python - "yield from iterable"与 "return iter(iterable)",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30187598/

相关文章:

python - 使 SQLalchemy 将字符串存储为小写的正确方法是什么?

python - 我正在尝试网络抓取网站,当我尝试将其转换为 csv 文件时,数据不会进入正确的列

python - 使用 Thrift 在 Python 脚本中运行 Hive-Query 时出现 `Connection Refused`

java - 为单个和多个对象创建对象容器

python - 如何使用.join?

Python 插值不适用于行

python-3.x - 使用 pip 安装 requirements.txt 文件时出现 TLS/SSL 问题

python-3.x - 选择日期之间的 Pandas 数据框中的行,无论年份如何

python-3.x - libc.musl-x86_64.so.1 : cannot open shared object file

python - "iterable"在Python中到底意味着什么?为什么我的实现 `__getitem__()` 的对象不是可迭代的?