`[]`和`list()'的行为有什么不同?

问题描述 投票:3回答:2
print(id([]) == id([]))
# prints 'True'

print(id(list()) == id(list()))
# prints 'False'

x = []
y = []
print(id(x) == id(y))
# prints 'False'

为什么list()[]的行为有不同,就上述代码而言?

python python-3.x list
2个回答
5
投票

在第三次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)
}

第一个[]创建的列表在第二个[]表达式之前消失,因此它的标题位于空闲列表中,然后它被第二个[]重用。 id值基于此标头的地址,因此两个列表具有相同的ID值。

相比之下,list()通过tp_newtp_init,而listtp_newPyType_GenericNew,它没有通过相同的自由名单。 PyType_GenericNew碰巧在不同的内存中分配两个列表,产生不同的ID值。


4
投票

id(object)返回对象的id。

如果变量引用的对象相等(具有相同的内容),则==表达式的计算结果为True。

所以当你每次创建一个新对象时使用list()构造函数,并且它的id是不同的,因此它的计算结果为false,即使新对象被立即丢弃,它首先被创建,因此它是不同的id。

相反,[]是文字(创建对象的更快方式)并且始终具有相同的ID,但是当它创建新对象时,新对象也获得它的新ID。

TLDR; []是一个文字,因此有一个固定的ID,list()创建一个新的对象,x=[] y=[]创建一个新的对象x和y,因此xy的id不一样,list()每次创建一个新的对象,因此不同的id每次通话。

此外x = []将比x = list()更快,但这只是一个脚注,我不知道如何使它变小,并把它像脚注:)

© www.soinside.com 2019 - 2024. All rights reserved.