Python调用父类方法-super

本文深入探讨了Python中super()函数的使用方法,包括在子类中调用父类已覆盖方法、确保正确初始化父类、在特殊方法覆盖中的应用及在多继承场景下的重要性。文章还介绍了方法解析顺序(MRO)的概念及其在super()调用中的作用。

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

  • 在子类中调用父类的某个已经被覆盖的方法,需要使用 super() 函数。
class Parent(object):

    def spam(self):
        print('Parent.spam')


class Child(Parent):

    def spam(self):
        print('Child.spam')
        super().spam()  # Call parent spam()


if __name__ == "__main__":
    c = Child()
    c.spam()

  • super() 函数的一个常见用法是在 init() 方法中确保父类被正确的初始化了。
class Parent(object):

    def __init__(self):
        self.x = 0


class Child(Parent):

    def __init__(self):
        super().__init__()
        self.y = 1


if __name__ == "__main__":
    c = Child()
    print(c.y, c.x)

  • super() 的还有一个常见用法出现在覆盖Python特殊方法的代码中。
class Proxy:
    def __init__(self, obj):
        self._obj = obj

    # Delegate attribute lookup to internal obj
    def __getattr__(self, name):
        return getattr(self._obj, name)

    # Delegate attribute assignment
    def __setattr__(self, name, value):
        if name.startswith('_'):
            super().__setattr__(name, value) # Call original __setattr__
        else:
            setattr(self._obj, name, value)


if __name__ == "__main__":
    p = Proxy(object)

  • _setattr_() 的实现包含一个名字检查。 如果某个属性名以下划线(_)开头,就通过 super() 调用原始的_setattr_() , 否则的话就委派给内部的代理对象 self._obj 去处理。 这看上去有点意思,因为就算没有显式的指明某个类的父类, super() 仍然可以有效的工作。
  • 在多继承中应该使用super,而不是直接用类.方法直接父类调用

Python继承的原理是根据一个所谓的方法解析顺序(MRO)列表。 这个MRO列表就是一个简单的所有基类的线性顺序表。

#例如
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
  • 为了实现继承,Python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止,而这个MRO列表的构造是通过一个C3线性化算法来实现的,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
    • 子类会先于父类被检查。
    • 多个父类会根据它们在列表中的顺序被检查。
    • 如果对下一个类存在两个合法的选择,选择第一个父类。

当你使用 super() 函数时,Python会在MRO列表上继续搜索下一个类。 只要每个重定义的方法统一使用 super() 并只调用它一次, 那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次。

然而,由于 super() 可能会调用不是你想要的方法,你应该遵循一些通用原则。 首先,确保在继承体系中所有相同名字的方法拥有可兼容的参数签名(比如相同的参数个数和参数名称)。 这样可以确保 super() 调用一个非直接父类方法时不会出错。 其次,最好确保最顶层的类提供了这个方法的实现,这样的话在MRO上面的查找链肯定可以找到某个确定的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值