当前位置: 首页 > 面试题库 >

为什么同一对象的不同方法具有相同的“ id”?

皇甫鸿远
2023-03-14
问题内容

我以为is运算符检查对象id的相等性。但事实并非如此:

>>> class A(object):
...   def f(): return 1
...   def g(): return 2
...
>>> a = A()
>>> a.f is a.g
False
>>> id(a.f) == id(a.g)
True

问题答案:

*Python *将相同的内存
位置用于方法a.fa.g,这是*两个对象,它们的生命周期不重叠,因此id对它们返回相同的标识。请参阅下面的详细说明。

从is运算符的文档中:

运算符是否测试对象标识:并且仅当x和y是同一对象时,x is y才是true。

从ID的文档中

返回对象的“身份”。这是一个整数(或长整数),在此对象的生存期内,此整数保证是唯一且恒定的。
具有不重叠生存期的两个对象可能具有相同的id()值。

说明

每当您通过class.name或查找方法时instance.name,都会重新创建该方法对象。Python每次都使用描述符协议将函数包装在方法对象中。

因此,当您查找id(a.f)或时id(a.g),将创建一个新的方法对象。

  1. 当您查找的ID时a.f,会在内存中创建其副本。该存储位置由返回id
  2. 由于没有对新创建方法的引用,因此GC回收了该方法( 现在可以再次使用内存地址 )。
  3. 获得ID的ID后a.g,将在相同的内存地址中创建它的副本,您可以id再次使用该地址进行检索。
  4. 您有 真实 ID的比较。

祝好运!



 类似资料:
  • 问题内容: 在以下代码中,我不明白为什么当它属于两个不同的对象时具有相同的ID? 问题答案: 我认为这是正在发生的事情: 取消引用时,将在内存中创建其副本。该存储位置由以下位置返回 由于没有引用到刚刚创建的方法的副本,因此GC将其回收,并且该内存地址再次可用 取消引用时,将在相同的内存地址(可用)中创建它的副本,您可以再次使用该地址。 第二个副本是GCd 如果您要运行一堆其他代码并再次检查实例方法

  • 问题内容: 我正在练习继承。 我有两个相似的类,我想将其同化为一个数组,因此我想将Object类用作超类,因为所有内容都是Object的子类。 因此,例如,我将T类和CT类放入一个名为all的数组中,如下所示: 我跳过了声明,因为那不是我的问题。 当我希望使用循环在数组内调用函数时,我真正的问题就变成了: T和CT分别涉及的类都具有beingShot方法,该方法是公共的。 Eclipse建议将它们

  • 问题内容: 我尝试过一些关于绑定和未绑定方法的代码。当我们调用它们时,我认为它们都会返回对象。但是,当我用于获取一些信息时,它返回的内容我并不理解。 IDE:Eclipse 插件:pydev 输出是… 为什么#1和#2返回相同的ID?他们不是不同的对象吗?如果我们分配和两个变量,#3,#4回报不同的ID。 我认为#3和#4表明它们不是同一对象,而是#1和#2 … 绑定方法的ID和未绑定方法的ID有

  • 以前我没有得到任何错误,但突然我开始得到错误:

  • 问题内容: 使用多处理模块时,我试图在流程中创建一个新对象。但是,有些事情使我感到困惑。 当我使用多处理模块时,新对象的ID是相同的 但是当我使用线程时,它们是不同的: 我想知道为什么它们不同。 问题答案: CPython中的id返回给定对象的指针。由于线程具有共享的地址空间,因此将在两个不同的位置分配对象的两个不同实例,并返回两个不同的ID(又称为虚拟地址指针)。 拥有自己的地址空间的单独进程不

  • 我试图理解java中同步块的概念。根据我读过的文档,我明白如果我们获取一个锁(使用实例变量的同步块),那么我们就不能在该类中的同一对象上获取同步锁。但是当我尝试实际使用以下片段时,我发现我的理解出了问题。 即我能够同时以两种不同的方法获取锁(同一实例变量上的同步块)。当线程启动时,它将转到run方法并无限期地等待,并且不会从同步块中出来。同时,如果我使用相同的线程调用stop方法,它会进入同步块并