有关python中字典分配的问题

时间:2019-11-13 16:28:17

标签: python dictionary

我想知道为什么这段代码会输出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被删除了?

2 个答案:

答案 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中。这就是为什么它不被删除