python - `[]` 和 `list()' 的行为有什么区别?

标签 python python-3.x list

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_newtp_init,而list tp_newPyType_GenericNew,它不经过相同的空闲列表。 PyType_GenericNew 恰好将两个列表分配到不同的内存中,产生不同的 ID 值。

关于python - `[]` 和 `list()' 的行为有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55586070/

相关文章:

java - 使用来自循环方法的列表内容更新列表

python - 我收到警告 <RuntimeWarning : invalid value encountered in sqrt>

python - 在 Python 命令行中使用 unicode 字符 (Python 3.4.1.)

python-3.x - 在 openpyxl 中加载和保存工作簿后丢失图像

python - Scrapy 没有按照 allowed_domains 过滤结果

python - 如何删除列表中重复的 "keys"并计算值的平均值

python - 如何以稳定的方式使用 pytest 断言列表?

python - 获取 m 个值中 n 个错误回答的行

python - 使用 python 将文本文件解析为矩阵

python - 如何在 Django REST Framework 中创建多个模型实例而无需重复的可写嵌套序列化程序?