You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中类方法访问方式不同导致id值差异的原因解析

类方法不同访问方式下id值差异的原因分析

问题现象

测试Python类方法时发现id值异常:定义MyClass类并创建实例obj1、obj2后,分别通过类和实例访问类方法classmethod,打印其id值,结果显示不同访问方式下id存在差异;且Python 3.9.12、3.10.7版本与3.8.10版本的输出表现不同。

测试代码

class MyClass:
    def method(self):
        return 'instance method called', self

    @classmethod
    def classmethod(cls):
        return 'class method called', cls

    @staticmethod
    def staticmethod():
        return 'static method called'

obj1 = MyClass()
obj2 = MyClass()

print(id(MyClass.classmethod), "MyClass")
print(id(obj1.classmethod), "obj1")
print(id(obj2.classmethod), "obj2")
print("------------------------")
print(id(MyClass.classmethod), MyClass.classmethod)
print(id(obj1.classmethod), obj1.classmethod)
print(id(obj2.classmethod), obj2.classmethod)

输出结果

140600363181376 MyClass
140600363181568 Obj1
140600363181376 Obj2
------------------------
140600363181568 <bound method MyClass.classmethod of <class '__main__.MyClass'>>
140600363181568 <bound method MyClass.classmethod of <class '__main__.MyClass'>>
140600363181568 <bound method MyClass.classmethod of <class '__main__.MyClass'>>

原因解析

1. 类方法的Descriptor特性

@classmethod装饰器创建的是一个descriptor对象,它的__get__方法会根据访问场景返回不同的对象:

  • 通过类访问(MyClass.classmethod):
    • 在Python 3.8及更早版本中,直接返回classmethod实例本身;
    • 在Python 3.9+版本中,会返回一个绑定到当前类的bound method对象(和通过实例访问返回的对象类型一致)。
  • 通过实例访问(obj1.classmethod):无论哪个Python版本,都会触发__get__方法,返回绑定到类的bound method对象(类方法绑定的是类,而非实例)。

2. 内存地址(id)的复用机制

Python中id()返回的是对象在内存中的唯一地址,但当一个对象被垃圾回收(不再被引用)后,新创建的对象可能复用这个地址。你输出中两次打印的id不一致,就是因为:

  • 第一次打印时,临时创建的对象(比如classmethod实例或临时bound method)在打印后就被销毁,内存地址被释放;
  • 第二次打印时,新创建的bound method对象复用了之前释放的地址,导致所有id看起来相同。

3. 如何判断是否为同一方法

不要依赖id()或直接用is判断bound method对象是否相同,因为每次访问都可能创建新的bound method实例。正确的做法是查看方法的__func__属性,它指向原始的函数对象:

print(MyClass.classmethod.__func__ is obj1.classmethod.__func__)  # 输出 True
print(MyClass.classmethod.__func__ is obj2.classmethod.__func__)  # 输出 True

所有访问方式得到的类方法,其__func__都指向同一个原始函数,这才是它们本质相同的证明。

内容的提问来源于stack exchange,提问作者Aayush Shah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:20:58