类中继承自同一方法的两个实例方法为何存在差异?
为何继承自同一方法的两个类方法在实例中存在差异?
嘿,这个问题其实挺戳中面向对象编程里一个容易被忽略的细节——尤其是在Python这类动态语言里!我来给你拆解一下最常见的原因:
核心原因:实例方法的「绑定机制」
咱们先举个你可能遇到的典型场景:
class Parent: def my_method(self): print("来自父类的方法") class Child(Parent): # 子类把父类的同一个方法赋值给两个不同的属性 method_a = Parent.my_method method_b = Parent.my_method
当你实例化Child并检查这两个方法是否相同时,会发现:
child = Child() print(child.method_a is child.method_b) # 输出 False!
这是因为:
Parent.my_method本身是一个未绑定的函数对象(没有和任何实例关联)。- 当你通过实例访问
method_a或method_b时,Python会自动把这个函数包装成一个绑定方法对象——这个对象会把当前实例和原函数绑定在一起,方便调用时自动传入self参数。 - 关键是:每次访问都会生成一个新的绑定方法实例,哪怕它们包装的是同一个底层函数。
如果你想验证底层函数其实是同一个,可以直接看绑定方法的__func__属性:
print(child.method_a.__func__ is child.method_b.__func__) # 输出 True!
其他可能的场景
除了绑定机制,还有几种情况也会导致这种差异:
- 方法被二次包装:如果子类对其中一个方法做了额外的包装(比如用lambda、自定义装饰器),那它就不再是原方法的引用了:
这时候class Child(Parent): method_a = Parent.my_method method_b = lambda self: Parent.my_method(self) # 新的lambda函数method_a和method_b的底层函数完全不同,实例中自然也不一样。 - 静态/类方法的例外:如果原方法是
@staticmethod或@classmethod,那通过实例访问时不会生成绑定方法,直接返回原对象,所以两个属性会指向同一个东西:class Parent: @staticmethod def static_method(): print("静态方法") class Child(Parent): s1 = Parent.static_method s2 = Parent.static_method child = Child() print(child.s1 is child.s2) # 输出 True
总结
简单来说:
- 实例方法通过实例访问时,每次都会生成新的绑定方法对象,导致
is判断为False,但底层函数是同一个。 - 静态/类方法不会触发绑定机制,所以引用保持一致。
- 如果方法被二次包装,那底层函数本身就变了,差异更明显。
内容的提问来源于stack exchange,提问作者ansavchenco
相关产品推荐
相关产品推荐

