未实现迭代器协议的迭代器定义:Test类是否不符合迭代器规范?
关于Python迭代器定义的疑问
根据Python官方定义,迭代器对象必须同时实现__iter__和__next__方法,二者共同构成迭代器协议:
迭代器对象本身必须支持以下两个方法,二者共同构成迭代器协议:
iterator.__iter__()返回迭代器对象本身。这是为了允许容器和迭代器都能用于for和in语句。
iterator.__next__()返回迭代器的下一个元素。若没有更多元素,则抛出StopIteration异常。
看下面这段代码:
class Test: def __init__(self, size): self.size = size def __iter__(self): return TestIter(self.size) class TestIter: def __init__(self, target=20): self.counter = 0 self.target = target def __next__(self): if self.counter > self.target: raise StopIteration self.counter += 1 return self.counter
按照定义,Test类和TestIter类都没有同时实现__iter__和__next__方法——Test只有__iter__,TestIter只有__next__,看起来都不符合迭代器的要求。但实际运行时,Test类却能像迭代器一样正常工作:
>>> for i in Test(5): ... print(i) ... 1 2 3 4 5 6 >>> >>> list(Test(5)) [1, 2, 3, 4, 5, 6] >>> >>> it = iter(Test(5)) >>> next(it) 1 >>> next(it) 2 >>> next(it) 3 >>> next(it) 4 >>> next(it) 5 >>> next(it) 6 >>> next(it) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/tmp/iterators.py", line 18, in __next__ raise StopIteration StopIteration >>>
那么从技术层面来说,Test类确实不是迭代器吗?
解答
是的,Test类确实不是迭代器,它是一个可迭代对象(Iterable),而非迭代器(Iterator)。
二者的核心区别:
- 可迭代对象仅需实现
__iter__方法,该方法返回一个迭代器对象即可 - 迭代器必须同时实现
__iter__和__next__方法,且__iter__必须返回自身
Test类能正常用于for循环、list()转换,是因为for循环会自动调用iter()函数获取迭代器——iter()会调用Test类的__iter__方法返回TestIter实例,之后再通过该实例的__next__方法遍历元素。也就是说,Test类只需要承担"提供迭代器"的职责,自身不需要成为迭代器。
另外,TestIter也不符合严格意义上的迭代器协议,因为它缺少返回自身的__iter__方法。如果要让它成为标准迭代器,只需补充该方法:
class TestIter: def __init__(self, target=20): self.counter = 0 self.target = target def __iter__(self): return self # 返回自身,符合迭代器协议 def __next__(self): if self.counter > self.target: raise StopIteration self.counter += 1 return self.counter
内容的提问来源于stack exchange,提问作者Amir reza Riahi
相关产品推荐
相关产品推荐

