为何访问同一类实例的同一方法每次都会生成新的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,和上面的判断等价
核心原因
绑定方法是动态生成的包装器
当你通过实例.方法名的方式访问方法时,Python并不会提前缓存这个绑定关系,而是每次访问都动态创建一个新的method对象——这个对象就是一个轻量包装器,内部保存了两个关键引用:绑定的实例(__self__)和底层的未绑定函数(__func__,也就是类定义里的那个函数对象)。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
相关产品推荐
相关产品推荐

