max*_*max 7 python iterator python-3.x
是否obj == iter(obj)意味着obj不能重复迭代,反之亦然?我没有在文档中看到任何这样的措辞,但根据这个评论,标准库通过测试检查对象是否可重复迭代 :if iter(obj) is obj
@agf:Python标准库的某些部分依赖于规范的这一部分; 它们通过测试检测某些东西是否是迭代器/生成器
if iter(obj) is obj:,因为真正的迭代器/生成器对象将__iter__定义为标识函数.如果测试为真,则转换为list允许重复迭代,否则,假设对象可重复迭代,并且可以按原样使用它.
- ShadowRanger 6月3日17:23
文档确实声明如果obj是迭代器,则需要iter(obj)返回obj.但我认为这并不足以得出结论,可以使用非重复可迭代对象来识别iter(obj) is obj.
所有迭代器都是迭代器,但并非所有迭代器都是迭代器.
迭代的唯一要求是它定义了一个__iter__()返回迭代器的方法:
需要为容器对象定义一个方法以提供迭代支持:
container.__iter__()
返回一个迭代器对象.
一个迭代器必须遵循迭代器协议,其中有两个要求:
它有一个返回对象本身的__iter__()方法:
iterator.__iter__()
返回迭代器对象本身.
它有一个__next__()方法可以在每次调用时返回下一个项目,并且一旦用尽,就会StopIteration 在每次后续调用时引发:
一旦迭代器的
__next__()方法引发StopIteration,它必须继续在后续调用中这样做.不遵守此属性的实现被视为已损坏.
这些要求意味着迭代器永远不会重复,而且,你总是可以确认一个可迭代通过确认是一个迭代器(因此根据定义不可重复的)iter(obj) is obj是True:
def is_unrepeatable(obj):
return iter(obj) is obj
Run Code Online (Sandbox Code Playgroud)
但是:由于iterable的唯一要求是iter(obj)返回一些迭代器,因此无法证明它是可重复的.一个iterable可以定义一个__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
Run Code Online (Sandbox Code Playgroud)
>>> x = Unrepeatable([1,2,3])
>>> list(x)
[1, 2, 3]
>>> list(x)
[]
>>> iter(x) is x
False
>>>
Run Code Online (Sandbox Code Playgroud)
我会毫不犹豫地称这样一个"伪造的迭代器"表现得很糟糕,我想不出你在野外找到一个的情况,但如上所述,它是可能的.