Python中子类调用父类普通方法为何需显式传第一个参数?
为什么继承的普通方法需要显式传第一个参数,而类方法不用?
哈哈,这个问题刚好戳中了Python方法绑定机制的核心差异,我来给你掰扯明白:
1. 普通实例方法的绑定逻辑
普通方法(没加任何装饰器的那种)本质是和实例绑定的函数。只有当你通过实例对象调用它时,Python才会自动把这个实例作为第一个参数(通常命名为self)隐式传进去。
但如果是直接通过类(不管是父类还是子类)调用这个方法,它就退化成了一个普通的独立函数——没有绑定任何实例,所以Python不会帮你自动传参数,必须显式把实例作为第一个参数传进去。
举个和你场景对应的例子:
class A: def f(self, x): print(f"self: {self}, x: {x}") class B(A): pass # 错误调用:通过类B调用继承的实例方法f,没传self B.f(1) # 会抛出 TypeError: A.f() missing 1 required positional argument: 'self' # 正确调用方式1:通过实例调用 b = B() b.f(1) # Python自动把b作为self传入,输出 self: <__main__.B object at 0x...>, x: 1 # 正确调用方式2:通过类调用,但显式传实例 B.f(b, 1) # 手动传入b作为self,效果和上面一样
2. 类方法的特殊绑定规则
类方法加了@classmethod装饰器,它的绑定对象是类本身,而不是实例。所以不管你是通过类调用(比如B.f(1))还是通过实例调用(b.f(1)),Python都会自动把当前类(这里是B)作为第一个参数(通常命名为cls)隐式传进去。
还是用例子看:
class A: @classmethod def f(cls, x): print(f"cls: {cls}, x: {x}") class B(A): pass # 通过类调用:自动传入B作为cls B.f(1) # 输出 cls: <class '__main__.B'>, x: 1 # 通过实例调用:同样自动传入B作为cls b = B() b.f(1) # 输出 cls: <class '__main__.B'>, x: 1
3. 继承不会改变方法的绑定类型
你可能误以为继承会把父类的实例方法变成类方法,但其实不会——父类的实例方法被子类继承后,它依然是实例方法,遵循实例方法的绑定规则。所以当你用子类的类去调用这个继承来的方法时,它还是未绑定的函数,必须显式传self参数(也就是一个实例)。
总结一下核心区别:
- 普通实例方法:仅通过实例调用时隐式传
self;通过类调用时是普通函数,需手动传第一个参数。 - 类方法:无论通过类还是实例调用,都会隐式传
cls(当前类)。 - 继承不改变方法的绑定属性,该是实例方法还是实例方法,该是类方法还是类方法。
内容的提问来源于stack exchange,提问作者Alexandr Zarubkin
相关产品推荐
相关产品推荐

