分离__iter__和__next__方法 [英] Separating the __iter__ and __next__ methods

查看:118
本文介绍了分离__iter__和__next__方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Python 3中,通过定义__iter____next__方法同时使一个类成为可迭代和迭代器是标准过程.但是我很难解决这个问题.以下面的示例为例,该示例创建仅产生偶数的迭代器:

In Python 3, it is standard procedure to make a class an iterable and iterator at the same time by defining both the __iter__ and __next__ methods. But I have problems to wrap my head around this. Take this example which creates an iterator that produces only even numbers:

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)

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

To my knowledge (correct me if I'm wrong), when I create the loop, an iterator is created by calling something like itr = iter(instance) which internally calls the __iter__ method. This is expected to return an iterator object (which the instance is due to defining __next__ and therefore I can just return self). To get an element from it, next(itr) is called until the exception is raised.

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

My question here is now: if and how can __iter__ and __next__ be separated, so that the content of the latter function is defined somewhere else? And when could this be useful? I know that I have to change __iter__ so that it returns an iterator.

要实现此目的的想法来自此网站( LINK ),没有说明如何实现.

Btw the idea to do this comes from this site (LINK), which does not state how to implement this.

推荐答案

听起来好像您在混淆迭代器可迭代对象.可迭代对象具有__iter__方法,该方法返回迭代器.迭代器具有__next__方法,该方法返回其下一个值或引发StopIteration.现在,在python中,声明,迭代器也是可迭代的(但而不是反之亦然),而iter(iterator) is iterator则是迭代器itr应该仅从其__iter__方法返回自身.

It sounds like you're confusing iterators and iterables. Iterables have an __iter__ method which returns an iterator. Iterators have a __next__ method which returns either their next value or raise a StopIteration. Now in python, it is stated that iterators are also iterables (but not visa versa) and that iter(iterator) is iterator so an iterator, itr, should return only itself from it's __iter__ method.

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

Iterators are required to have an __iter__() method that returns the iterator object itself so every iterator is also iterable and may be used in most places where other iterables are accepted

在代码中:

class MyIter:
   def __iter__(self):
       return self

   def __next__(self):
       # actual iterator logic

如果要创建自定义迭代器类,最简单的方法是从 collections.abc.Iterator 如上定义了__iter__(它也是collections.abc.Iterable的子类).然后,您需要的只是

If you want to make a custom iterator class, the easiest way is to inherit from collections.abc.Iterator which you can see defines __iter__ as above (it is also a subclass of collections.abc.Iterable). Then all you need is

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

当然,有一种更简单的方法来制作迭代器,那就是使用生成器函数

There is of course a much easier way to make an iterator, and thats with a generator function

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]


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


Just for reference, this is (simplified) code for an abstract iterator and iterable

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

这篇关于分离__iter__和__next__方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆