Python bug?懒惰对象具有隐藏状态

Vek*_*eky 2 python enumerate lazy-evaluation

考虑一下(Python 3.3):

a=enumerate([2,3,5])
print(list(a))
print(list(a))
Run Code Online (Sandbox Code Playgroud)

你真的希望两个打印电话打印不同的东西吗?我也不.

如果用set/ tuple或替换列表,也会发生同样的事情dict.如果你enumeratemap或替换对象也会发生这种情况filter,但奇怪的是,如果你用它替换它range.

也许这是一个功能.但这是非常令人惊讶的,没有记录(至少我没有找到任何关于它的东西),而且不一致(范围的工作原理不同).你怎么看?

Mar*_*ers 7

enumerate()返回一个迭代器,就像其他调用一样.你只能遍历迭代器一次; 然后就筋疲力尽了.

您可以使用生成器函数自己创建这样的迭代器:

def somelist_generator():
    somelist = [1, 2, 3]
    while somelist:
        yield somelist.pop()
Run Code Online (Sandbox Code Playgroud)

如果你要循环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
Run Code Online (Sandbox Code Playgroud)

next()调用尝试从it迭代器中获取另一个值; 它已经为空,因此StopIteration引发了异常.这个异常表明没有更多的元素可以得到,这就是为什么你第二次尝试从迭代器获取任何东西时最终得到一个空列表:

>>> list(it)
[]
Run Code Online (Sandbox Code Playgroud)

range()没有返回一个迭代.它返回一个范围对象,代表一个内存有效的数字系列; 只需要存储开始,结束和步幅,其他一切都可以从这3点得出.