考虑这个(Python 3.3):
a=enumerate([2,3,5])
print(list(a))
print(list(a))
你真的希望有两个打印电话可以打印不同的东西吗? 我也没有。
如果您将列表替换为set
,tuple
或dict
,则会发生同样的情况。如果您将enumerate
对象替换为map
或filter
,也会发生这种情况,但奇怪的是,如果将其替换为range
则不会。
也许这是一个功能。但这是非常令人惊讶的,没有记录(至少我没有找到任何关于它的东西),而且不一致(范围的工作原理不同)。你觉得怎么样?
答案 0 :(得分:7)
enumerate()
和其他调用一样返回一个迭代器。你只能循环一次迭代器;然后就筋疲力尽了。
您可以使用生成器函数自己创建这样的迭代器:
def somelist_generator():
somelist = [1, 2, 3]
while somelist:
yield somelist.pop()
如果您要循环somelist_generator()
,则列表somelist
将被清空。你只能这样做一次,因为.pop()
删除了元素:
>>> it = somelist_generator()
>>> for i in it:
... print(i)
...
3
2
1
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
next()
调用尝试从it
迭代器获取另一个值;它已经为空,因此引发了StopIteration
异常。这个异常表明没有更多的元素可以获得,这就是为什么你第二次尝试从迭代器获取任何东西时最终得到一个空列表的原因:
>>> list(it)
[]
range()
不返回迭代器。它返回一个range object,代表一个内存有效的数字系列;只需要存储开始,结束和步幅,其他一切都可以从这3点得出。
答案 1 :(得分:2)
行为记录在http://docs.python.org/3/glossary.html#term-iterator
一个值得注意的例外是尝试多次迭代的代码 经过。 ...尝试使用迭代器只会返回相同的内容 在前一次迭代传递中使用的耗尽迭代器对象,制作 它看起来像一个空容器。