【发布时间】:2014-02-16 01:49:36
【问题描述】:
我了解标准规定确实如此,但我正在努力寻找其根本原因。
如果它总是简单地返回self,那还需要什么?
您显然始终可以访问该对象,因为您在该对象上调用iter,那么拥有它有什么需要?
【问题讨论】:
我了解标准规定确实如此,但我正在努力寻找其根本原因。
如果它总是简单地返回self,那还需要什么?
您显然始终可以访问该对象,因为您在该对象上调用iter,那么拥有它有什么需要?
【问题讨论】:
想象一下,您想编写对任何类型的可迭代对象进行迭代的代码。通常你只需要写一个for 声明或理解,但让我们明确地做for 在幕后所做的事情,让事情更明显:
i = iter(iterable)
while True:
try:
val = next(i)
except StopIteration:
break
else:
do_stuff(val)
如果您不执行该第一行,您的代码将无法处理列表、字符串、元组或除迭代器之外的任何内容。
但是,如果您执行第一行,那么iter(iterable) 最好返回一个迭代器,否则您的代码将无法使用迭代器。
您可能想知道为什么iter 没有这个就不能做正确的事?毕竟,当给定一个具有__len__ 和__getitem__ 但没有__iter__ 的对象时,它确实具有创建迭代器的魔力,那么为什么它不能也具有魔力呢?如果它有__next__ 但没有__iter__,则只返回它的参数?这是一个语言设计问题,但一般来说,Python 会尽量减少魔法。使不完全序列可迭代的魔法是必要的,因为在将迭代协议添加到语言之前,这样的序列就已经存在(在广泛的第三方代码中),而且为了简化事情的小小好处,删除它太难了。
【讨论】:
for 语句(或理解)......它在幕后执行此代码。”需要说清楚吗?
for 循环应该与可迭代对象一起工作,因此for i in something: 自动调用iter(something) 来获取迭代器并迭代所述迭代器。现在,如果迭代器也不是可迭代的(即没有定义 __iter__),则不能将 for 循环与迭代器一起使用,即:
items = [1, 2, 3]
# this would work
for item in items: pass
# this wouldn't
it = iter(items)
for item in it: pass
因此,迭代器也应该是可迭代的。另一种方法是“以某种方式检测”迭代器而不是对它们调用iter,这种方法既笨拙又脆弱(你会如何决定呢?)。
【讨论】:
i.__iter__() 提出AttributeError,在做回退之前对于基于索引的迭代,首先检查i.__next__是否存在,如果存在,则返回i。
__iter__ 中的真正错误,恰好表现为AttributeError,将导致Python 抱怨缺少__next__ 应该是什么可迭代。我在类似的“异常 X 意味着它不是 Y 鸭子”策略中遇到了糟糕的诊断问题:print(*y()) 其中def y(): raise TypeError; yield 声称argument after * must be a sequence, not generator。
for 循环和其他需要使用可迭代对象的代码可以无条件地调用 iter 在它们正在迭代的事物上,而不是分别处理迭代器和其他可迭代对象。特别是,非迭代器可能有一个名为next 的方法,我们希望能够将它们与迭代器区分开来。
【讨论】:
next 的方法。 (这是可能是next被重命名为__next__的原因,当然。)
__iter__() 旨在返回对象上的迭代器。什么是对已经是迭代器的对象的迭代器? self,当然。
【讨论】:
iter(an_iterator)?为什么必须被定义? (有充分的理由,但你没有说出任何理由)。