Python 3 调用 "list" 有奇怪的副作用

Python 3 call to "list" has odd side-effects

考虑以下两个代码片段。

片段 1:

l = range(10)
list(l)
m = reversed(l)
list(m)
l = range(-1)
list(l)
list(m)

片段 2:

l = range(10)
m = reversed(l)
l = range(-1)
list(l)
list(m)

它们之间的唯一区别是代码段 2 在其前半部分不调用 list(l)list(m)

奇怪的是,片段 1 returns 中对 list(m) 的最终调用

[] 

而片段 2 中对 list(m) 的最终调用 returns

[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]  

这些是不同的值!

这不是我所期望的行为。据推测,代码段 1 中对 list(l)list(m) 的早期调用触发了某种内存优化;请问有人能准确地向我解释发生了什么吗?

>>> l = range(10)
>>> list(l)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> m = reversed(l)
>>> list(m)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> l = range(-1)
>>> list(l)
[]
>>> list(m)
[]
>>>
>>> l = range(10)
>>> m = reversed(l)
>>> l = range(-1)
>>> list(l)
[]
>>> list(m)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

谢谢。

reversed returns 一个一次性的迭代器:在你第一次将它提供给 list (它从反向项目构建一个列表)后它就用完了。

在随后的运行中,它将生成空列表,因为提供的迭代器 m 已耗尽,无法生成更多值:

m = reversed(l)
print(m) # <list_reverseiterator at 0x7fd2b8518fd0>
list(m)  # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
list(m)  # []  (exhausted)

在您的第二个片段中,您没有像在第一个片段中那样在 m 上调用 list,因此没有耗尽它。

你只需要调用一次,最后就会得到你看到的列表。