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

为何访问同一类实例的同一方法每次都会生成新的bound method?

为什么访问同一实例的同一方法会生成新的绑定方法?

每次通过类实例访问其方法时,哪怕是同一个实例、同一个方法,得到的绑定方法(bound method)都是全新的对象——这从代码里m1 is m2返回False就能看出来,但m1 == m2却返回True,这背后是Python对绑定方法的实现逻辑决定的。

代码示例

class MyClass:
    def my_method(self):
        print(f"调用绑定到 {self} 的方法")


m_unbound = MyClass.my_method
print(f"{type(m_unbound)} {hash(m_unbound)}")  # 输出:<class 'function'> 8783579798336
m_unbound(None)

mc = MyClass()
m1 = mc.my_method
print(f"{type(m1)} {hash(m1)}")  # 输出:<class 'method'> 122173
m1()

m2 = mc.my_method  # 原本以为会和m1是同一个对象
print(f"{type(m2)} {hash(m2)}")  # 输出:<class 'method'> 122173
m2()

print(m1 == m2)  # True
print(m1 is m2)  # False,为什么会这样?
print(id(m1) == id(m2))  # False,和上面的判断等价

核心原因

  1. 绑定方法是动态生成的包装器
    当你通过实例.方法名的方式访问方法时,Python并不会提前缓存这个绑定关系,而是每次访问都动态创建一个新的method对象——这个对象就是一个轻量包装器,内部保存了两个关键引用:绑定的实例(__self__)和底层的未绑定函数(__func__,也就是类定义里的那个函数对象)。

  2. is与==的判断逻辑不同

    • is判断的是两个对象是否是内存中的同一个实例,因为每次访问都会生成新的包装器,所以m1 is m2返回False。
    • 而绑定方法的__eq__方法被特意实现为:只要两个绑定方法的__self__(绑定的实例)和__func__(底层函数)都完全相同,就返回True——这也是为什么m1 == m2返回True的原因。

补充验证说明

下面的代码进一步验证了上述逻辑:

print(m1.__self__ is m2.__self__)  # True,绑定的是同一个实例
print(m1.__func__ is m2.__func__)  # True,指向同一个底层函数
print(m2.__func__ is m_unbound)  # True,底层函数就是类的未绑定方法

为什么Python要这么设计?

  • 实现简单:不需要为每个实例维护一个方法绑定的缓存表,减少了复杂度。
  • 性能影响可忽略:绑定方法的包装器非常轻量,创建成本极低,几乎不会对程序性能造成影响。
  • 符合使用场景:绝大多数情况下,开发者只关心方法是否绑定到正确的实例和函数,并不在意包装器本身的同一性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:20:32