所有的迭代器都是可迭代的,但并非所有的可迭代都是迭代器。
可迭代的唯一requirement 是它定义了一个返回迭代器的__iter__() 方法:
需要为容器对象定义一个方法来提供迭代支持:
container.__iter__()
返回一个迭代器对象。
iterator 必须遵循迭代器协议,它有两个要求:
-
它有一个__iter__() 方法that returns the object itself:
iterator.__iter__()
返回迭代器对象本身。
-
它有一个__next__() 方法,该方法在每次调用时返回下一项,一旦用尽,就会引发StopIteration on every subsequent call:
一旦迭代器的__next__() 方法引发StopIteration,它必须在后续调用中继续这样做。不遵守此属性的实现被视为已损坏。
这些要求意味着迭代器永远不可重复,并且您始终可以通过确认 iter(obj) is obj 是 True 来确认可迭代器是迭代器(因此根据定义不可重复):
def is_unrepeatable(obj):
return iter(obj) is obj
然而:因为迭代的唯一要求是iter(obj)返回一些迭代器,你不能证明它是可重复的。一个可迭代对象可以定义一个 __iter__() 方法,该方法在每次调用时返回一个具有不同行为的迭代器:例如,它可以返回一个迭代器,该迭代器在第一次调用时迭代其元素,但在随后的调用中,返回一个迭代器,该迭代器立即引发StopIteration。
这种行为会很奇怪(也很烦人),但并不被禁止。这是一个非迭代器的不可重复可迭代类的示例:
class Unrepeatable:
def __init__(self, iterable):
self.iterable = iterable
self.exhausted = False
def __iter__(self):
if self.exhausted:
return
else:
self.exhausted = True
yield from self.iterable
>>> x = Unrepeatable([1,2,3])
>>> list(x)
[1, 2, 3]
>>> list(x)
[]
>>> iter(x) is x
False
>>>
我会毫不犹豫地称这样的“假迭代器”行为不端,而且我想不出你会在野外找到一个,但如上所示,这是可能的。