print(id([]) == id([]))
# prints 'True'
print(id(list()) == id(list()))
# prints 'False'
x = []
y = []
print(id(x) == id(y))
# prints 'False'
对于上述代码,为什么 list()
的行为与 []
不同?
最佳答案
在您的第三个 id
比较中,您正在比较具有重叠生命周期的两个对象的 ID 值。根据 id
函数的约定,这必须返回 False。您会看到与 list()
相同的行为。
在前两个 id
比较中,所涉及的对象具有不重叠的生命周期。具有非重叠生命周期的对象的 ID 值是否碰巧相同是一个实现细节,您不应该依赖它是一种方式还是另一种方式。行为如有更改,恕不另行通知。
在当前的 CPython 中,ID 值恰好与 []
相同,因为 []
使用 BUILD_LIST
操作码,调用 C 函数 PyList_New
, 并且 PyList_New
使用释放列表头结构的空闲列表来加速分配:
PyObject *
PyList_New(Py_ssize_t size)
{
...
if (numfree) {
numfree--;
op = free_list[numfree];
_Py_NewReference((PyObject *)op);
当列表被释放时,保存元素指针的缓冲区被释放,但是(直到最大空闲列表大小)头部保存关于对象类型、引用计数、容量等信息的信息。goes on the free list :
static void
list_dealloc(PyListObject *op)
{
...
if (numfree < PyList_MAXFREELIST && PyList_CheckExact(op))
free_list[numfree++] = op;
else
Py_TYPE(op)->tp_free((PyObject *)op);
Py_TRASHCAN_SAFE_END(op)
}
由第一个 []
创建的列表在第二个 []
表达式之前死亡,因此它的 header 进入空闲列表,然后被第二个重用[]
。 id
值基于此 header 的地址,因此两个列表具有相同的 ID 值。
相比之下,list()
会经过tp_new
和tp_init
,而list
的 tp_new
是 PyType_GenericNew
,它不经过相同的空闲列表。 PyType_GenericNew
恰好将两个列表分配到不同的内存中,产生不同的 ID 值。
关于python - `[]` 和 `list()' 的行为有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55586070/