所有迭代器都是可迭代对象,但并非所有可迭代对象都是迭代器。
唯一的要求 https://docs.python.org/3/library/stdtypes.html#container.__iter__可迭代的一个特点是它定义了一个__iter__()
返回迭代器的方法:
需要为容器对象定义一种方法来提供迭代支持:
container.__iter__()
返回一个迭代器对象。
An iterator https://docs.python.org/3/library/stdtypes.html#iterator-types必须遵循迭代器协议,它有两个要求:
-
它有一个__iter__()
method 返回对象本身 https://docs.python.org/3/library/stdtypes.html#iterator.__iter__:
iterator.__iter__()
返回迭代器对象本身。
-
它有一个__next__()
方法,每次调用时返回下一个项目,并且一旦耗尽,就会引发StopIteration
在随后的每次通话中 https://docs.python.org/3/library/stdtypes.html#iterator.__next__:
一旦迭代器的__next__()
方法引发StopIteration
,它必须在后续调用中继续这样做。不遵守此属性的实现将被视为已损坏。
这些要求意味着迭代器永远不可重复,并且您始终可以通过确认以下内容来确认可迭代器是迭代器(因此根据定义不可重复)iter(obj) is obj
is True
:
def is_unrepeatable(obj):
return iter(obj) is obj
However:因为可迭代的唯一要求是iter(obj)
回报some迭代器,你can't证明它is可重复。一个可迭代对象可以定义一个__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
>>>
我会毫不犹豫地称这种“假迭代器”行为不良,而且我无法想象你会在野外找到一个迭代器的情况,但正如上面所演示的,这是可能的。