关于python中字典分配的问题

问题描述 投票:0回答:2

我不知道为什么这段代码会产生打印输出True:

rec = {"Name" : "Python", "Age":"20", "Addr" : "NJ", "Country" : "USA"}
id1 = id(rec)
del rec
rec = {"Name" : "Python", "Age":"20", "Addr" : "NJ", "Country" : "USA"}
id2 = id(rec)
print(id1 == id2)

据我所知,如果我们要更改id1中的某些内容,那么rec也将更改。那么为什么该代码不删除id1,因为rec被删除了?

python dictionary
2个回答
0
投票

如果想要特定于CPython的非常技术性的答案,请参考Python实现(我在这里假设大多数人都将其默认为当他们说“ Python”时表示):Python中许多常见的对象类型是从所谓的“自由列表”中分配的东西,它是一个数组,或者在某些情况下,我认为是一个链表,其中包含已经分配了内存的相同类型的对象。例如,这意味着,可以通过为单个字典反复重复使用相同的内存分配,而不是反复地对其进行分配/释放,来快速创建和销毁许多短期字典。

例如,对于dict对象,可以在此处查看自由列表:https://github.com/python/cpython/blob/61289d436661025a3111065482275d49a4850b8d/Objects/dictobject.c#L252

((还有一个单独的字典键,我现在将忽略。)

[创建新的dict时,new_dict函数首先检查new_dict中是否有空插槽,如果有,则重新使用它(稍作伪代码重新解释):

free_list

稍后,在PyDictObject *mp; if (numfree) { mp = free_list[--numfree]; _Py_NewReference((PyObject *)mp); } else { // Allocate a new PyDictObject // Note, we do NOT put this on the freelist yet since it's still in use; // we'll do that later mp = PyObject_GC_New(PyDictObject, &PyDict_Type); } 中,当剩余zero个对您的对象的引用时被调用,如果dict_dealloc上有空间,我们将对象保留在那里而不是释放其内存:

dict_dealloc

要清楚,请注意,存储在free_list中的if (numfree < PyDict_MAXFREELIST && Py_TYPE(mp) == &PyDict_Type) free_list[numfree++] = mp; else Py_TYPE(mp)->tp_free((PyObject *)mp); 确实不是意味着它们的任何键或值也都保留在内存中。这仅适用于PyDictObject本身,其中包含指向键/值的数组的指针,以及一些其他内部簿记功能。

[如果碰巧您的初始free_list释放了PyDictObject中的一个插槽,那么立即创建一个新的dict(无论其内容如何)将使用相同的插槽,因此具有相同的del rec,因为在CPython中free_list仅返回对象的内存地址。当然,即使没有免费名单,这也很可能偶然发生。


-3
投票

id1是一个自变量。它已从记录分配一个值。现在,如果rec被删除,则id1中将存储一个单独的值,该值不在该字典rec中。这就是为什么不删除它的原因

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