分离__iter__和__next__方法

问题描述 投票:2回答:2

在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)

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

我现在的问题是:__iter____next__是否以及如何分开,以便后一个函数的内容在其他地方定义?什么时候这可能有用?我知道我必须更改__iter__以便它返回一个迭代器。

在这个想法之间来自这个网站(qazxsw poi),它没有说明如何实现这一点。

python python-3.x iterator iterable
2个回答
8
投票

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

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

在代码中:

__iter__()

如果你想创建一个自定义迭代器类,最简单的方法是继承class MyIter: def __iter__(self): return self def __next__(self): # actual iterator logic ,你可以看到如上定义collections.abc.Iterator(它也是__iter__的子类)。那么你需要的只是

collections.abc.Iterable

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

class MyIter(collections.abc.Iterator):
    def __next__(self):
        ...

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

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]

0
投票

我想我现在已经掌握了这个概念,即使我不完全理解@FHTMitchell的文档段落。我遇到了一个关于如何分离这两种方法的例子,并希望记录下来。

我发现的是一个非常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 ,可以清楚地区分迭代和迭代器(这是我混淆的原因)。

基本上,您首先将可迭代定义为单独的类:

basic tutorial

class EvenNumbers: def __init__(self, max_): self.max = max_ def __iter__(self): self.n = 0 return EvenNumbersIterator(self) 方法只需要一个定义了__iter__方法的对象。因此,您可以这样做:

__next__

这将迭代器部分与可迭代类分开。现在有意义的是,如果我在可迭代类中定义class EvenNumbersIterator: def __init__(self, source): self.source = source def __next__(self): if self.source.n <= self.source.max: result = 2 * self.source.n self.source.n += 1 return result else: raise StopIteration ,我必须返回对实例本身的引用,因为它基本上一次完成2个作业。

© www.soinside.com 2019 - 2024. All rights reserved.