我想知道为什么这段代码会输出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被删除了?
答案 0 :(得分:0)
如果您想要一个针对 CPython 的非常技术性的答案,请参考Python实现(我在这里假设大多数人都将其默认为当他们说“ Python”时表示):许多常见对象Python中的类型是从称为“自由列表”的东西中分配的,“空闲列表”是一个数组,或者在某些情况下,我认为是一个链表,该列表包含已为其分配内存的相同类型的对象。例如,这意味着,可以通过为单个字典重复使用相同的内存分配,而不是反复地对其进行分配/释放,来快速创建和销毁许多短期字典。
例如,dict
个对象的空闲列表可以在这里查看:https://github.com/python/cpython/blob/61289d436661025a3111065482275d49a4850b8d/Objects/dictobject.c#L252
(还有一个单独的字典键,我现在将忽略。)
创建新的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);
}
稍后,在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
本身,其中包含指向键/值的数组的指针,以及一些其他内部簿记功能。
如果最初的del rec
释放了free_list
中的一个插槽,则立即创建一个新的dict(无论其内容如何)将使用相同的插槽,因此具有相同的{ {1}},因为在CPython id()
中仅返回对象的内存地址。当然,即使没有免费名单,这也可能很容易发生。
答案 1 :(得分:-3)
id1是一个自变量。它已从记录分配一个值。现在,如果rec被删除,则id1中将存储一个单独的值,该值不在该字典rec中。这就是为什么它不被删除