类有 iter 但不是 next

Dav*_*542 5 python iterator language-lawyer

对于迭代器协议,您创建一个__iter__and__next__方法。然而,下面的情况又如何呢:

class Item:
    def __init__(self):
        self.name = 'James'
    def __iter__(self):
        return self
Run Code Online (Sandbox Code Playgroud)

现在我可以做:

>>> i=Item()
>>> iter(i)
<__main__.Item instance at 0x10bfe6e18>
Run Code Online (Sandbox Code Playgroud)

但不是:

>>> next(i)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: instance has no next() method
Run Code Online (Sandbox Code Playgroud)

据我所知,迭代器/可迭代的定义是:

  • 可迭代有方法__iter__
  • 迭代器有方法__next__

那么这是否意味着我上面的项目是一个 Iterable 但不是一个 Iterator?或者两者都不是,因为执行以下操作是行不通的:

>>> for item in i:
...     print (item)
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: instance has no next() method
Run Code Online (Sandbox Code Playgroud)

请注意,这将是定义了迭代器方法的完整类:

class Item:
    def __init__(self):
        self.name = 'James'
        self.i = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.i >= len(self.name): raise StopIteration
        value = self.name[self.i]
        self.i += 1
        return value
Run Code Online (Sandbox Code Playgroud)

Blc*_*ght 7

您的定义大部分是正确的,但不完全正确。

  • 如果一个对象具有返回迭代器的方法,则该对象是可迭代的。__iter__
  • 如果一个对象具有在迭代时获取下一个值的方法,则该对象就是迭代器。__next__但 Python 中的迭代器也应该是可迭代的。它们都应该有一个__iter__返回 的方法self

您的第一个示例有一个__iter__方法,但因为它返回self并且该对象不是迭代器(因为它没有__next__方法),所以它也不是真正有效的可迭代对象。

要使非迭代器可迭代,您需要返回一些其他有效迭代器的对象。一种偷偷摸摸的方法是创建__iter__一个生成器方法(通过yield在其实现中使用)。但是,如果您要返回一些值序列,您也可以只返回该序列上的迭代器。

最后一个代码块中的类确实是一个迭代器。但是,如果您想让它成为一个不是其自己的迭代器的可迭代对象(也许是因为您希望能够对其进行多次迭代),您可能会想要更像这样的东西:

class Item:
    def __init__(self):
        self.name = 'James'
    def __iter__(self):
        return iter(self.name)
Run Code Online (Sandbox Code Playgroud)