要理解super()
,可以先记住它的核心作用:帮你找到“父类或兄弟类”的方法,尤其是当子类自己重写了某个方法,但你还想调用被重写的“原版”(父类或兄弟类的版本)时,就需要它。
先看个最简单的例子:单继承中用super()
比如你写了一个子类继承父类,子类重写了父类的方法,但想在子类方法里顺便调用一下父类的原版方法:
class 父类:def 打招呼(self):print("我是父类")class 子类(父类):def 打招呼(self):# 先调用父类的“打招呼”方法super().打招呼() # 等价于 super(子类, self).打招呼()# 再加上子类自己的逻辑print("我是子类")obj = 子类()
obj.打招呼()
# 输出:
# 我是父类
# 我是子类
这里super()
就相当于“父类的代理”,帮你找到父类的打招呼
方法。不用显式写父类.打招呼(self)
,如果以后父类名字改了,super()
的代码也不用动,更方便维护。
关键:super()
按“MRO顺序”找方法
super()
找方法不是瞎找的,而是按照“方法解析顺序(MRO)”来的。MRO就是一个类继承时,查找方法的固定顺序(可以通过类名.__mro__
查看)。
比如有个复杂的继承关系:D继承B和C,B和C都继承A
,它的MRO可能是:D -> B -> C -> A -> object
(具体顺序Python会自动算)。
如果在B
的方法里用super()
,它会从MRO中B
后面的类开始找,也就是先找C
,再找A
,最后找object
。
这一点在“多重继承”(一个类继承多个父类)时特别有用。比如多个父类有同名方法,super()
会按MRO顺序依次调用,避免混乱(这就是文档说的“协作多重继承”)。
super()
的参数怎么用?
super()
可以带参数,也可以不带,最常用的是“不带参数”的情况:
-
零参数
super()
(最常用)
只能在类的方法里用(比如实例方法、类方法)。此时Python会自动帮你填参数:- 对实例方法(比如
def method(self): ...
):super()
等价于super(当前类, self)
。 - 对类方法(比如
@classmethod def cls_method(cls): ...
):super()
等价于super(当前类, cls)
。
上面的例子里,
子类
的打招呼
方法中,super()
就是自动绑定了当前类(子类)
和self(实例对象)
。 - 对实例方法(比如
-
带两个参数
super(type, obj_or_type)
- 第一个参数
type
:指定从哪个类之后开始找(比如super(B, obj)
,就从MRO中B
后面的类开始找)。 - 第二个参数
obj_or_type
:如果是实例对象,必须是type
的实例;如果是类,必须是type
的子类。
比如在上面的
D->B->C->A
例子中,想在D
的方法里直接调用C
的方法,可以用super(B, self).方法()
(因为MRO中B
后面是C
)。 - 第一个参数
注意点
super()
不仅能调用方法,还能找属性(比如父类的变量)。- 不要在嵌套函数(比如方法里再定义一个函数)里用零参数
super()
,可能会找错。 - 多重继承时,
super()
的调用顺序完全依赖MRO,所以设计类时要保证同名方法的参数一致,否则可能出错。
总结
super()
的核心是:按MRO顺序,帮你找到父类或兄弟类的方法/属性。单继承时,它就是“父类的快捷方式”;多重继承时,它能按规则协调多个父类的调用,避免混乱。用的时候记住:在类的方法里直接写super().xxx()
,大部分情况都够用了。