“ []”和“ list()”的行为有何不同?

时间:2019-04-09 06:04:13

标签: 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()为什么表现与[]不同?

2 个答案:

答案 0 :(得分:5)

在第三次id比较中,您将比较两个具有重叠生命周期的对象的ID值。根据{{​​1}}函数的约定,它必须返回False。您将看到与id相同的行为。

在前两个list()比较中,所涉及的对象具有不重叠的生存期。具有非重叠生存期的对象的ID值是否恰好相同是实现的详细信息,您不应依赖于它是一种方式。行为如有更改,恕不另行通知。

在当前的CPython中,ID值恰好与id相同,因为[]使用BUILD_LIST操作码,该操作码调用C函数PyList_New和{{ 1}}使用释放列表列表头结构的免费列表来加快分配速度:

[]

释放列表时,将释放保存元素指针的缓冲区,但(最大释放列表大小)将释放包含有关诸如对象类型,引用计数,容量等信息的标头。goes on the free list:< / p>

PyList_New

由第一个PyObject * PyList_New(Py_ssize_t size) { ... if (numfree) { numfree--; op = free_list[numfree]; _Py_NewReference((PyObject *)op); 创建的列表在第二个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值。

相反,[]经过idlist(),而tp_new的{​​{1}}是tp_init,而不会通过相同的空闲列表。 list恰好在不同的内存中分配了两个列表,从而产生了不同的ID值。

答案 1 :(得分: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()快,但这只是一个注脚,我不知道如何缩小它的大小,只能像注脚一样把它放进去:)