要理解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(),大部分情况都够用了。
