【问题标题】:Which Python iterables are consumable?哪些 Python 迭代器是可消耗的?
【发布时间】:2021-02-27 00:08:51
【问题描述】:

如果我理解正确,我们在 Python 中有:

  • Iterables = __iter__() 已实现
  • Iterators = __iter__() 返回 self & __next__() 已实现
  • Generators = 使用yield 语句或生成器表达式创建的迭代器。

问题:以上类别是否始终/从不消耗?

我所说的消耗品是指遍历它们会“破坏”可迭代对象;比如 zip()(消耗品)与 range()(非消耗品)。

【问题讨论】:

  • 小修正:yielddef 语句中创建一个生成器,但您也可以使用生成器表达式创建一个生成器,例如(x for x in [1,2,3]).
  • 回过头来提到这个页面对于查找这些概念的 Python 文档定义很有用:docs.python.org/3.8/library/collections.abc.html

标签: python iterator


【解决方案1】:

所有个迭代器被消耗;您可能不这么认为的原因是,当您使用类似

的可迭代对象时
for x in [1,2,3]:

for 循环在幕后为您创建了一个新的迭代器。事实上,list 不是一个迭代器; iter([1,2,3]) 返回 list_iterator 类型的内容,而不是列表本身。


关于您在评论中链接到的示例,而不是

class PowTwo:    
    def __init__(self, max=0):
        self.max = max

    def __iter__(self):
        self.n = 0
        return self

    def __next__(self):
        if self.n <= self.max:
            result = 2 ** self.n
            self.n += 1
            return result
        else:
            raise StopIteration

在返回它的过程中修改迭代器的副作用,我会做类似的事情

class PowTwoIterator:    
    def __init__(self, max=0):
        self.max = max
        self._restart()

    def _restart(self):
        self._n = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self._n <= self.max:
            result = 2 ** self._n
            self._n += 1
            return result
        else:
            raise StopIteration

现在,您可以修改对象状态的唯一方法是明确地这样做(即使这样做也不应该轻易完成,因为 _n_restart 都被标记为不是公共接口的一部分)。

名称的变化提醒你,这首先是一个迭代器,而不是一个可以提供独立迭代器的可迭代对象。

【讨论】:

  • 谢谢!那么 range() 对象不是迭代器而是可迭代的?
  • 正确;特别是,range.__iter__ 的 CPython 实现返回 range_iterator 类型的东西。
  • 非常感谢!最后一个问题:我看到了不可消耗的自定义迭代器,因此我感到困惑(例如本教程中的“PowTwo”类:programiz.com/python-programming/iterator)。那么这被认为是不好的做法,还是只是所有内置的 Python 迭代器都遵循非消耗性的经验法则?
  • 我认为这是不好的做法,如果只是因为__iter__ 有副作用。它可能看起来像您可以创建该类的两个独立迭代器 (p = PowTwo(); i1 = iter(p); i2 = iter(p)),但由于 i1 is i2 为真,推进一个推进另一个。
  • 这是有道理的。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 1970-01-01
  • 2017-09-10
  • 1970-01-01
  • 2015-01-13
相关资源
最近更新 更多