在临时对象共享相同内存地址的情况下,“is”如何工作? [重复]

问题描述 投票:0回答:1

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

python python-3.x cpython
1个回答
3
投票

问题是,当您执行

a[:] is a[:]

时,两个对象

not
位于同一地址 - 为了使恒等运算符 is 比较两个对象,两个操作数都必须存在 - 因此,仍然存在对当
is
的本机代码实际运行时左侧的对象。

另一方面,当您执行

id(a[:]),id(a[:])

时,一旦

id
函数调用完成,第一次调用时括号内的对象将没有任何引用,并被销毁,释放内存块以供使用第二个
a[:]
    

© www.soinside.com 2019 - 2024. All rights reserved.