在临时对象共享相同内存地址的情况下,`is` 是如何工作的?

How does `is` work in the case of ephemeral objects sharing the same memory address?

请注意,这个问题可能(是?)特定于 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 可能知道列表的临时副本已经创建并正在等待垃圾收集,并且它只是有效地重新使用相同的内存位置。如果答案也可以clarify/confirm,那就太好了。

两个不可变的对象,共享相同的地址,正如您所担心的,彼此无法区分。

问题是,当您执行 a[:] is a[:] 时,两个对象 不是 在同一地址 - 为了让身份运算符 is 比较两者对象,两个操作数都必须存在 - 因此,当 is 的本机代码实际上是 运行.

时,仍然存在对左侧对象的引用

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

使用