分离__iter__和__next__方法 [英] Separating the __iter__ and __next__ methods
问题描述
在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屋!