这些天我一直在玩 Python,我意识到 Python 如何将 id(address) 分配给新实例(int 和 list)的一些有趣方式。
例如,如果我使用一个数字(或两个不同的数字)来调用 id 函数,它会返回相同的结果。例如
>>> id(12345)
4298287048
>>> id(12345)
4298287048
>>> id(12345)
4298287048
>>> id(12342) #different number here, yet still same id
4298287048
此外,当我先声明变量然后用它调用 id() 时,结果会像这样交替出现。
>>> x = []; id(x)
4301901696
>>> x = []; id(x)
4301729448
>>> x = []; id(x)
4301901696
>>> x = []; id(x)
4301729448
有人可以解释一下这背后的 Python 工作吗?另外,有没有一本书或一个网站可以让我了解 Python 的这一部分(分配内存地址、幕后工作等),因为我从 python documentation 中找不到什么?
最佳答案
您正在创建一个新对象没有任何其他引用,并且当对象在 id()
完成后再次销毁时,Python 会重新使用内存位置。在 CPython 中,id()
的结果 恰好 是对象的内存位置。来自id()
function documentation :
CPython implementation detail: This is the address of the object in memory.
id(12345)
行创建了一个新的 int()
实例;因为它作为参数绑定(bind)到 id()
它有 1 个引用。 id()
确定内存位置,并返回该结果。在返回时,参数被清理并且对 int()
实例的引用计数下降到 0,Python 将其清理。内存被释放。
下一行创建一个新的 int()
实例。在同一位置有可用内存,因此可以重复使用。
相反,当您第一次绑定(bind)没有名称的新对象时,您创建了一个对该对象的额外引用并且它没有被清除。内存未释放,新对象将不得不使用新的内存地址。
这部分也有记录,同样来自 id()
文档:
This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same
id()
value.
强调我的。
重新绑定(bind)时(x = []
当 x
已经设置时)Python 首先 创建一个新对象,然后 重新绑定(bind) x
以指向该新对象。这会在新列表创建后解除旧列表的绑定(bind)。这意味着当创建新的列表对象时,旧的内存位置仍然被占用。
将其映射到特定步骤:
- 您使用
id() == 4301901696
创建了一个对象。 4301901696
绑定(bind)到x
->4301901696
的引用计数为 1。- 您使用
id() == 4301729448
创建了一个对象。 4301901696
未绑定(bind)x
。4301901696
的引用计数降至 0 并从内存中清除。4301729448
绑定(bind)到x
。4301729448
的引用计数为 1。- 您创建了一个新对象,
4301901696
为空,因此新对象得到id() == 4301901696
。 4301729448
未绑定(bind)x
。4301729448
的引用计数降至 0 并从内存中清除。4301901696
绑定(bind)到x
。4301901696
的引用计数为 1。- 等等
这也是文档的一部分,assignment statement documenation告诉您订单分配发生在:
An assignment statement evaluates the expression list [...] and assigns the single resulting object to each of the target lists, from left to right.
其中 表达式列表 是 =
符号右侧的所有内容。
关于Python 交替引用新实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24086367/