为什么类需要__iter __()来返回迭代器?

sat*_*k.t 9 python iterator class python-3.x

为什么类需要定义__iter__()返回self,以获取类的迭代器?

class MyClass:
    def __init__(self):
        self.state = 0

    def __next__(self):
        self.state += 1
        if self.state > 4:
            raise StopIteration
        return self.state

myObj = MyClass()
for i in myObj:
    print(i)
Run Code Online (Sandbox Code Playgroud)

控制台日志:

Traceback (most recent call last):
   for i in myObj:
TypeError: 'MyClass' object is not iterable
Run Code Online (Sandbox Code Playgroud)

答案/sf/answers/691898161/,说

迭代器是具有next(Python 2)或__next__(Python 3)方法的对象.

添加以下内容的任务:

def __iter__(self):
   return self
Run Code Online (Sandbox Code Playgroud)

是返回定义方法的迭代器或类的对象__next__().

但是,当MyClass在myObj = MyClass()行中实例化时,不是返回MyClass对象(定义__next__()方法)的任务,而是由__new__()MyClass实例化了吗?

类定义__next__()方法的对象不是自己的迭代器吗?

我已经研究了问题__iter__方法中返回self的用途是什么?构建一个基本的Python迭代器,但我仍然无法理解__iter__()返回self 的方法的原因.

Ray*_*ger 10

为什么__iter __()方法是必要的问题的答案是for for循环总是通过调用对象上的iter()来获得迭代器.这就是为什么即使是iterator也需要一个__iter __()方法来处理for循环.后电话ITER() ,然后它调用__()__next对所得迭代以获得值.

创建iterables和迭代器的规则是:

1)Iterables有一个返回迭代器的__iter __()方法.

2)迭代器有一个__next __()方法,它返回一个更新状态的值,并在完成时引发StopIteration.

3)迭代器本身有一个返回self__iter __()方法.这意味着所有迭代器都是可自我迭代的.

具有返回self__iter __()方法的迭代器的最后一条规则好处是它允许我们传递部分消耗的迭代器:

>>> s = 'hello world'
>>> it = iter(s)
>>> next(it)
'h'
>>> next(it)
'e'
>>> list(it)     # Doesn't start from the beginning
['l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
Run Code Online (Sandbox Code Playgroud)

这是另一个依赖于迭代器可自动迭代而不重新启动的示例:

>>> s = 'hello world'
>>> it = iter(s)
>>> list(zip(it, it))
[('h', 'e'), ('l', 'l'), ('o', ' '), ('w', 'o'), ('r', 'l')]
Run Code Online (Sandbox Code Playgroud)

笔记:

1)制作可迭代的另一种方法是提供一个__getitem __()方法,该方法接受连续索引并在完成时引发IndexError.这就是str对象在Python 2中的迭代方式.

2)像文件这样的对象是它们自己的迭代器.这意味着您可以直接在文件对象上调用next().它还意味着文件不能有多个独立的迭代器(文件对象本身具有跟踪文件中位置的状态).

3)上面描述的迭代器设计模式不是Python特有的.它是许多OOP语言的通用设计模式:https://en.wikipedia.org/wiki/Iterator_pattern


Jim*_*ard 5

这不是已经通过__new__()方法完成了吗

不,__new__只是另一种方法,它不会自动__iter__为对象创建。

类定义__next__()方法的对象不会自己成为迭代器吗?

不一定,因为您的第一堂课定义__next__但未__iter__显示。__next__需要的,如果你需要支持迭代,因为它产生的价值。__iter__是需要的,因为这是在for语句中对对象调用的内容,以便它获得迭代器。

你可以有一个只定义__next__并且有点工作的类(它是有限的)但是,它需要从 peoples 返回__iter__。例如,该类MyClass返回一个CustomIter仅定义的类__next__

class MyClass:
    def __iter__(self): 
        return CustomIter()

class CustomIter(object):

    def __init__(self): 
        self.state = 0

    def __next__(self): 
        self.state += 1
        if self.state > 4:
            raise StopIteration
        return self.state
Run Code Online (Sandbox Code Playgroud)

您需要__iter__在一个对象上定义一个对象,该对象将返回另一个__next__已定义对象(可能是它自己)。


如果您的课程定义__iter__为:

def __iter__(self): return self
Run Code Online (Sandbox Code Playgroud)

那么你需要__next__type(self)(类)上定义,因为你返回了实例本身。__next__将被调用,self直到无法产生更多值。

另一种情况是__iter__简单地返回另一个定义的对象__next__(根据我的第一个示例)。您也可以通过制作__iter__发电机来做到这一点。

例如:

class MyClass:
    def __init__(self):
        self.state = 0

    def __iter__(self): 
        for i in range(10): yield i
Run Code Online (Sandbox Code Playgroud)

没有定义__next__. 什么时候iter调用它:

g = iter(MyClass())
Run Code Online (Sandbox Code Playgroud)

它返回一个g定义的生成器__next__

g = iter(MyClass())

g.__next__() # 0
g.__next__() # 1
Run Code Online (Sandbox Code Playgroud)