Python什么时候为空列表创建新的列表对象?

16

以下内容我能理解:

>>> [] is []
False

考虑到列表是可变的,我期望每次在表达式中出现[]时,它都会成为一个新的空列表对象。然而,使用这个解释,下面的结果让我感到惊讶:

id([]) == id([])
True

为什么?这是什么解释?


我敢打赌,对于所有版本的Python来说,id([]) == id([])都不是True(是的,我已经检查过了)。cPython倾向于以这种方式重新分配内存,这是一种实现细节。 - roippi
@roippi 我认为这实际上是快速malloc/free/malloc的偶然现象。a = []; b = []; id(a) == id(b) # 这是False - Silas Ray
@roippi -- 我敢打赌,在某些Python版本中,它有时候可以工作,有时候不行,这取决于GC运行的时间。 - Michael Lorton
1个回答

15
在第一个例子中,[]并不是[],这是因为列表是可变的。如果它们不可变,则可以安全地映射到相同的列表而不会有问题。
在第二个例子中,id([])创建一个列表,获取其标识符,然后释放该列表。下一次再创建一个列表,但是"将其放置在相同的位置",因为没有发生太多其他事情。 id仅在对象的生存期内有效,在此情况下,其生命周期几乎为零。
来自 id文档的内容:

这个整数(或长整数)在对象的生命周期内保证是唯一且恒定的。 生存期不重叠的两个对象可能具有相同的id()值。


反汇编注释:
   0 LOAD_GLOBAL              0 (id)    # load the id function
   3 BUILD_LIST               0         # create the first list
   6 CALL_FUNCTION            1         # get the id
   9 LOAD_GLOBAL              0 (id)    # load the id function
  12 BUILD_LIST               0         # create the second list
  15 CALL_FUNCTION            1         # get the id
  18 COMPARE_OP               2 (==)    # compare the two ids
  21 RETURN_VALUE                       # return the comparison

请注意,没有STORE_FAST来保留该列表。因此,在传递给id函数后立即被丢弃。


我记得不久前你回答了同样的问题;P - zhangxaochen
不是这个,也许不是你,但可能是一个重复的。 - zhangxaochen
1
回答得好。例如,在 def f(x, y): return id(x) == id(y) 中,当 xy 都需要保持存活时,f([], []) 的计算结果为 False - Loax
准确的说,只要它们的生命周期重叠,它们必须根据定义具有唯一的键。 - mhlester
@mhlester 非常感谢! - Aamir Rind
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接