首页 > 解决方案 > 在临时对象共享相同内存地址的情况下,“is”如何工作?

问题描述

请注意,这个问题可能(是?)特定于 CPython。

假设您有一些列表,并检查列表的副本以确认彼此的身份:

>>> a=list(range(10))
>>> b,c=a[:],a[:]
>>> b is c
False
>>> id(b), id(c)
(3157888272304, 3157888272256)

那里没有很大的震动。但如果我们以一种更短暂的方式来做这件事,一开始事情可能看起来有点奇怪:

>>> a[:] is a[:]
False  # <- two ephemeral copies not the same object (duh)
>>> id(a[:]),id(a[:])
(3157888272544, 3157888272544)   # <- but two other ephemerals share the same id..? hmm....

...直到我们认识到这里可能发生了什么。我没有通过查看 CPython 实现来确认这一点(我几乎看不懂 c++,所以说实话,这将是浪费时间),但至少看起来很明显,即使两个对象具有相同的 id,CPython 也很聪明足以知道它们不是同一个对象。

假设这是正确的,我的问题是:CPython 使用什么标准来确定两个临时对象是否不是同一个对象,因为它们具有相同的 id(可能是出于效率原因 - 见下文)?它是否可能正在查看它被标记为垃圾收集的时间?创建时间?或者是其他东西...?

我关于为什么它们具有相同 id 的理论是,很可能,CPython 知道列表的临时副本已经制作并等待被垃圾收集,并且它只是有效地重用相同的内存位置。如果答案也可以澄清/确认这一点,那就太好了。

标签: pythonpython-3.xcpython

解决方案


两个不可变的对象,共享相同的地址,在你看来,彼此无法区分。

问题是,当你做a[:] is a[:]这两个对象不在同一个地址时——为了让身份运算符is比较两个对象,两个操作数都必须存在——所以,当的本机代码is实际上正在运行。

另一方面,当您id(a[:]),id(a[:])在第一次调用时,括号内的对象在函数调用完成后立即没有任何引用id,并被销毁,释放内存块以供第二次使用a[:]


推荐阅读