【问题标题】:What is the purpose of __iter__ returning the iterator object itself?__iter__ 返回迭代器对象本身的目的是什么?
【发布时间】:2015-09-09 19:32:18
【问题描述】:

我不明白为什么__iter__ 特殊方法只返回它所调用的对象(如果它是在迭代器上调用的)。它本质上只是一个标志,表明该对象是一个迭代器吗?

编辑:实际上,我发现“这是允许容器和迭代器与 forin 语句一起使用所必需的。” https://docs.python.org/3/library/stdtypes.html#iterator.iter

好吧,我是这样理解的:在编写for 循环时,您可以指定一个可迭代对象或一个要循环的迭代器。但 Python 最终需要一个循环迭代器,因此它会调用 __iter__ 方法,无论它给定什么。如果给它一个迭代器,__iter__ 方法将产生一个迭代器,如果给它一个迭代器,__iter__ 方法同样会产生一个迭代器(给定的原始对象)。

【问题讨论】:

  • 它只返回相同的对象如果该对象是一个迭代器。如果对象是一个iterable,那么__iter__ 可以返回一些其他将成为迭代器的对象。见this question
  • doc
  • 但如果它是一个迭代器,我仍然不明白你为什么要让它自己返回。
  • 您需要返回一个迭代器,您可以将其传递给next 以获取下一个对象。如果实例实现了__next__,则可以返回实例本身。
  • 你的问题是“为什么迭代器是可迭代的”?

标签: python python-3.x


【解决方案1】:

当你使用for x in something 循环某个东西时,循环实际上首先调用iter(something),所以它可以使用。一般来说,for循环大致相当于这样:

something_iterator = iter(something)
while True:
   try:
       x = next(something_iterator)

       # loop body

   except StopIteration:
       break

因此,正如您自己已经弄清楚的那样,为了能够遍历迭代器,即当 something 已经是迭代器时,迭代器在调用 iter() 时应该始终返回自己。所以这基本上确保了迭代器也是可迭代的。

【讨论】:

  • 我假设您的意思是 except StopIteration 而不是 catch StopIteration
【解决方案2】:

这取决于你调用 iter 的对象。如果一个对象已经是一个迭代器,那么将它转换为一个迭代器不需要任何操作,因为它已经是一个。但是如果对象不是iterator,而是iterable,那么就会从对象构造一个迭代器。

列表对象就是一个很好的例子:

>>> x = [1, 2, 3]
>>> iter(x) == x
False
>>> iter(x)
<list_iterator object at 0x7fccadc5feb8>
>>> x
[1, 2, 3]

列表是可迭代的,但它们本身不是迭代器。 list.__iter__ 的结果不是原来的列表。

【讨论】:

    【解决方案3】:

    Python 中,当您尝试使用loops 时,或尝试遍历任何对象,如下所示..

    让我们试着理解list对象..

    >>> l = [1, 2, 3] # Defined list l
    

    如果我们遍历上面的列表..

    >>> for i in l:
    ...     print i
    ... 
    1
    2
    3
    

    当您尝试在 list l 上执行此操作时,iteration,Python for 循环检查 l.__iter__() 哪个实习生返回一个迭代器对象。

    >>> for i in l.__iter__():
    ...     print i
    ... 
    1
    2
    3
    

    要了解更多,让我们自定义list 并创建一个新的列表类..

    >>> class ListOverride(list):
    ...     def __iter__(self):
    ...         raise TypeError('Not iterable')
    ... 
    

    在这里,我创建了 ListOverride 类,该类从 list 实习生 inherited 并覆盖 list.__iter__ 方法来提高 TypeError

    >>> ll = ListOverride([1, 2, 3])
    >>> ll
    [1, 2, 3]
    

    我已经使用ListOverride 类创建了一个新列表,并且由于它是列表对象,它应该以与list 相同的方式进行迭代。

    >>> for i in ll:
    ...     print i
    ... 
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 3, in __iter__
    TypeError: Not iterable
    

    如果我们尝试iterate 超过ListOverride 对象ll,我们最终会得到NotIterable 异常..

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-17
      • 1970-01-01
      • 2018-06-15
      • 2017-03-19
      • 2014-07-30
      • 2017-10-11
      • 2014-05-27
      • 2017-03-20
      相关资源
      最近更新 更多