【Python】Super函数

文章详细介绍了Python中的super函数在子类继承父类时的作用,包括如何调用父类方法,以及在单继承和多继承情况下的应用。super()函数可以根据MRO(方法解析顺序)来决定调用哪个父类的方法,这在处理多继承问题时尤其有用。同时,文章提到了使用super避免代码重复和依赖于父类名的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

子类继承父类的时候,要使用父类的方法,需要使用到super函数

介绍

super([type[, object-or-type]])

函数说明
返回一个代理对象,它会将方法调用委托给 type 的父类或兄弟类。
参数说明
type:类,可选参数;
object-or-type:对象或类,一般是self,也是可选参数;
返回值是代理对象。
参数作用:第二个参数决定了调用父类的顺序,比如self,就是调用super函数的对象本身,它有一个__mro__属性,决定了按什么顺序调用父类的方法;第一个参数决定了从哪个类开始调用,一般也可以是本身类,即从本身这个类的顺序中的下一个类开始调用该方法
查看super的原型

help(super)

输出结果如下

Help on class super in module builtins:
 
class super(object)
 |  super() -> same as super(__class__, <first argument>)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |          super().meth(arg)
 |  This works for class methods too:
 |  class C(B):
 |      @classmethod
 |      def cmeth(cls, arg):
 |          super().cmeth(arg)

super 类是一个继承自 object 的类,super() 函数就是对该类的实例化;
调用 super() 实例化之后,返回一个 super 对象;
super() 参数有四种搭配,具体看上述输出;

单继承使用

使用super调用父类方法

class A:
    def funA(self):
        print("执行 A ,输出橡皮擦")
class B(A):
    def funB(self):
        # 注意 super() 函数的用法
        super().funA()
        print("执行 B ,输出铅笔")
 
b = B()
b.funB()

在单继承的层级结构中,super 可以直接引用父类,即在子类中不需要使用父类名调用父类方法,而使用 代理对象(super 对象) 去调用,这样的好处就是当父类名改变或继承关系发生改变时,我们不需要对调用进行反复修改。

多继承情况下使用

super使用缺省值时调用顺序

class A:
    def run(self):
        print('AAA')
 
class B:
    def run(self):
        print('BBB')
 
class C:
    def run(self):
        print('CCC')
 
class D(A, B, C):
    def run(self):
        super().run()
 
d = D()
d.run()

此时输出的结果是 AAA,可以看到 super 匹配到的数据是 A 类中的 run 函数,下面修改一下各类中 run 函数的名称,使其存在差异。

如果第一个父类中没有相应方法

class A:
    def run1(self):
        print('AAA')
 
class B:
    def run2(self):
        print('BBB')
 
class C:
    def run3(self):
        print('CCC')
 
class D(A, B, C):
    def run(self):
        # 调用 B 中 run2
        super().run2()
 
d = D()
d.run()

当一个类继承多个类时,如果第一个父类中没有提供该方法,当前类实例就会通过 mro 属性进行向上搜索,如果到 object 类都没有检索到该方法,就会引发 AttributeError 异常。

使用指定父类方法

class A:
    def run(self):
        print('AAA')
 
class B:
    def run(self):
        print('BBB')
 
class C:
    def run(self):
        print('CCC')
 
class D(A, B, C):
    def run(self):
        # 调用 C 中 run
        super(B, self).run()
 
d = D()
d.run()

显然就应该调用该顺序中B类的下一个类C类的方法(重要)

此时输出的结果是 CCC,该结果输出表示了使用 super 函数之后,可以使用 super(类,self) 指定以哪个类为起点检索父类中的方法,上述代码设置的 B,就表示从 B 开始检索,后续找到了 C 类,其中包含 run() 方法,所以输出 CCC。

可以使用__mro__ 属性查看顺序表

补充 mro 属性的说明

MRO 是 method resolution order,即方法解析顺序,其本质是继承父类方法时的顺序表。
在 Python 中可以使用内置属性 mro 查看方法的搜索顺序

class A:
    def run(self):
        print('AAA')
 
class B:
    def run(self):
        print('BBB')
 
class C:
    def run(self):
        print('CCC')
 
class D(A, B, C):
    def run(self):
        # 调用 C 中 run
        super(B, self).run()
 
print(D.__mro__)

输出的结果如下所示:

(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>)

修改一下继承顺序,可以得到不同的输出结果

(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.B'>, <class 'object'>)

在搜索方法的时候,是按照 mro 的输出结果从左到右进行顺序查找的,逻辑如下:
A. 找到方法,停止检索;
B. 没有找到,继续检索下一类;
C. 如果到最后都没有找到,程序报错

补充 super函数的用途

(1)避免在改动父类名称时还需改动子类调用方法的代码
(2)在子类中按照一套内置的顺序自动调用父类的方法
(3)多用于多继承问题中,解决查找顺序(MRO)、重复调用(钻石继承)等种种问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值