分离__iter__和__next__方法

Doc*_*ven 2 python iterator iterable python-3.x

在Python 3中,通过定义__iter____next__方法,使类成为可迭代和迭代器是标准过程.但我有问题要绕过这个问题.以此示例创建一个仅生成偶数的迭代器:

class EvenNumbers:

    def __init__(self, max_):
        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

        raise StopIteration

instance = EvenNumbers(4)

for entry in instance:
    print(entry)
Run Code Online (Sandbox Code Playgroud)

据我所知(如果我错了,请纠正我),当我创建循环时,通过调用itr = iter(instance)内部调用__iter__方法的内容来创建迭代器.这应该返回一个迭代器对象(实例是由于定义__next__,因此我可以返回self).要从中获取元素,next(itr)直到引发异常时才会调用它.

在这里我想问的是现在:是否以及如何能__iter____next__分离,从而使后者的功能的内容被定义别的地方?什么时候这可能有用?我知道我必须改变__iter__它以便它返回一个迭代器.

顺便说一句,这个想法来自这个网站(LINK),它没有说明如何实现这个.

FHT*_*ell 8

听起来你混淆了迭代器迭代.Iterables有一个__iter__返回迭代器的方法.迭代器有一个__next__方法可以返回它们的下一个值或者引发一个StopIteration.现在在python中,声明迭代器也是可迭代的(但反之亦然),iter(iterator) is iterator因此迭代器itr应该只返回它自己的__iter__方法.

迭代器需要有一个__iter__()返回迭代器对象本身的方法,因此每个迭代器也是可迭代的,并且可以在大多数接受其他迭代的地方使用

在代码中:

class MyIter:
   def __iter__(self):
       return self

   def __next__(self):
       # actual iterator logic
Run Code Online (Sandbox Code Playgroud)

如果你想创建一个自定义迭代器类,最简单的方法是继承collections.abc.Iterator你可以看到__iter__如上定义的定义(它也是它的子类collections.abc.Iterable).那么你需要的只是

class MyIter(collections.abc.Iterator):
    def __next__(self):
        ...
Run Code Online (Sandbox Code Playgroud)

当然有一种更简单的方法来制作迭代器,并且具有生成器功能

def fib():
    a = 1
    b = 1
    yield a
    yield b
    while True:
        b, a = a + b, b
        yield b

list(itertools.takewhile(lambda x: x < 100, fib()))
# --> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
Run Code Online (Sandbox Code Playgroud)

仅供参考,这是抽象迭代器和迭代的(简化)代码

from abc import ABC, abstractmethod

class Iterable(ABC):

    @abstractmethod
    def __iter__(self):
        'Returns an instance of Iterator'
        pass

class Iterator(Iterable, ABC):

    @abstractmethod
    def __next__(self):
        'Return the next item from the iterator. When exhausted, raise StopIteration'
        pass

    # overloads Iterable.__iter__
    def __iter__(self):
        return self
Run Code Online (Sandbox Code Playgroud)

  • 如果你定义了`__iter__`,那么这个对象就是**可迭代的**。如果您定义“__next__”,则该对象是一个**迭代器**。在 **iterator** 对象上,您应该设置 __iter__` 以返回对象本身,正如我所说,它是一个 **iterator**。**迭代器**是**可迭代对象**,当迭代(例如for循环)时,它们返回自身。 (3认同)