Pun*_*ngh 3 python list python-3.x
print(id([]) == id([]))
# prints 'True'
print(id(list()) == id(list()))
# prints 'False'
x = []
y = []
print(id(x) == id(y))
# prints 'False'
Run Code Online (Sandbox Code Playgroud)
关于上述代码,为什么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);
Run Code Online (Sandbox Code Playgroud)
当列表被释放时,保存元素指针的缓冲区将被释放,但是(最大空闲列表大小)包含有关对象类型,对象数量,引用计数,容量等信息的标头将进入空闲列表:
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)
}
Run Code Online (Sandbox Code Playgroud)
由第一个创建的列表在[]第二个[]表达式之前消失,因此其标题进入空闲列表,然后由第二个重新使用[]。该id值基于此标头的地址,因此两个列表具有相同的ID值。
相反,list()通过tp_new和tp_init,而list的tp_new是PyType_GenericNew,则不在同一空闲列表中。PyType_GenericNew碰巧将两个列表分配到不同的内存中,从而产生不同的ID值。