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

Python3中类实例是否共享类方法?id与is结果矛盾解惑

这是个非常棒的问题,刚好戳中了Python方法绑定的核心细节,咱们一步步拆解清楚:

一、a.something 和 b.something 的内存地址疑惑

首先要明确:当你通过实例访问类定义的方法时,Python会动态创建一个绑定方法对象(bound method),这个对象会把实例和类中的原始函数绑定在一起。

那为什么你测试时id(a.something)和id(b.something)的数值相同?这是Python内存复用的小把戏:

  • 当你调用id(a.something)时,临时创建的绑定方法对象在获取完id后就没有被引用了,会被垃圾回收机制释放内存;
  • 紧接着调用id(b.something)时,新创建的绑定方法对象刚好复用了之前释放的那块内存地址,所以id数值一致。

但这两个绑定方法本质上是完全不同的对象,你换一种方式测试就能看出来:

# 先把两个绑定方法存起来,避免被立即回收
meth_a = a.something
meth_b = b.something
print(meth_a is meth_b)  # 输出 False,说明是不同对象
print(id(meth_a), id(meth_b))  # 这里的id可能不同,也可能相同,全看内存分配情况

你之前写的id(a.something) is id(b.something)其实是个“伪测试”——因为两次id调用中间,第一个绑定方法已经被销毁了,比较的是两个不同对象的id数值,而非对象本身。

二、a.something() 的调用解析机制

当你尝试调用a.something()时,Python的属性查找和方法绑定流程是这样的:

  1. 先在实例a的__dict__(实例自身的属性字典)里找something——显然找不到,因为我们没给a单独绑定这个属性;
  2. 接着去a的类MyClass的__dict__里查找,找到了类定义的something函数;
  3. Python自动把这个函数包装成绑定方法对象,把实例a作为第一个参数(也就是我们常写的self)预绑定进去;
  4. 最后调用这个绑定方法时,它会自动调用类中的原始something函数,并把a传递进去。

⚠️ 注意哦:你当前的something定义没有self参数,所以直接调用a.something()会报错——Python会强行传入实例a作为第一个参数,但函数不接受任何参数。正确的类方法定义应该是:

class MyClass:
    def something(self):
        pass

另外要强调:类中的MyClass.something是唯一的函数对象,所有实例的绑定方法都是基于这个原始函数创建的,只是绑定的实例不同而已。

三、为什么实例的属性列表里会有something

当你用dir(a)查看实例的可用属性时,dir()函数的逻辑是:遍历实例自身的属性,再遍历类及所有父类的属性,最后整理成有序列表。所以类中定义的something方法会被包含进来,因为它是可以通过实例a访问到的属性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:43:54