Python中super()方法

在面向对象编程中,子类经常要调用父类的方法,在Python中,也不例外。

为了调用父类(超类)的一个方法,可以使用 super() 函数,比如:

class A:
    def spam(self):
        print('A.spam')

class B(A):
    def spam(self):
        print('B.spam')
        super().spam()  # Call parent spam()

super() 函数的一个常见用法是在 __init__() 方法中确保父类被正确的初始化了:

class A:
    def __init__(self):
        self.x = 0

class B(A):
    def __init__(self):
        super().__init__()
        self.y = 1

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)
__setattr__() 的实现包含一个名字检查。 如果某个属性名以下划线(_)开头,就通过 super() 调用原始的 __setattr__() , 否则的话就委派给内部的代理对象 self._obj 去处理。 这看上去有点意思,因为就算没有显式的指明某个类的父类, super() 仍然可以有效的工作。

super() 有个令人吃惊的地方是它并不一定去查找某个类在MRO中下一个直接父类, 你甚至可以在一个没有直接父类的类中使用它。

class A:
    def spam(self):
        print('A.spam')
        super().spam()
如果你试着直接使用这个类就会出错:


>>> a = A()
>>> a.spam()
A.spam
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 4, in spam
AttributeError: 'super' object has no attribute 'spam'

>>>

>>> class B:
...     def spam(self):
...         print('B.spam')
...
>>> class C(A,B):
...     pass
...
>>> c = C()
>>> c.spam()
A.spam
B.spam
>>>

你可以看到在类A中使用 super().spam() 实际上调用的是跟类A毫无关系的类B中的 spam() 方法。

由于  super()  可能会调用不是你想要的方法,你应该遵循一些通用原则。 首先,确保在继承体系中所有相同名字的方法拥有可兼容的参数签名(比如相同的参数个数和参数名称)。 这样可以确保  super()  调用一个非直接父类方法时不会出错。 

### Python `super()` 关键字的使用说明 `super()` 是 Python 中用于调用父类方法的一个内置函数。它的主要作用是在继承层次结构中简化对父类方法的调用,尤其是在多层继承的情况下能够保持代码的可读性和可维护性。 #### 基本功能 在 Python 3 中,`super()` 不再需要显式传递参数即可调用父类的方法[^2]。这使得代码更加简洁明了。具体来说,`super()` 返回一个代理对象,该对象允许我们调用当前类的父类中的方法。 #### 调用方式 以下是 `super()` 的典型用法: ```python class ParentClass: def __init__(self, name): self.name = name def greet(self): print(f"Hello from {self.name}!") class ChildClass(ParentClass): def __init__(self, name, age): super().__init__(name) # 调用父类的构造函数 self.age = age def introduce(self): super().greet() # 调用父类的方法 print(f"I am {self.age} years old.") ``` 在这个例子中,`ChildClass` 继承自 `ParentClass` 并重写了其初始化方法 (`__init__`) 和另一个方法 (`introduce`)。通过 `super()`,我们可以方便地调用父类的实现部分而不必硬编码父类名。 #### 多继承场景下的应用 当存在多个基类时,`super()` 可以按照 Method Resolution Order (MRO)[^4] 来决定调用顺序。下面是一个简单的多继承示例: ```python class A: def method(self): print("A's method") class B(A): def method(self): super().method() print("B's method") class C(A): def method(self): super().method() print("C's method") class D(B, C): def method(self): super().method() print("D's method") d_instance = D() d_instance.method() ``` 运行上述程序会依次打印出: ``` A's method C's method B's method D's method ``` 这是因为 MRO 遵循广度优先原则决定了各方法被调用的实际次序。 #### 自动化与灵活性 相比传统写法如 `ParentClass.some_method(self)`,采用 `super()` 提供了更高的自动化程度以及更好的适应未来可能的变化的能力。即使修改了继承链或者增加了新的中间层,只要遵循正确的设计模式,就不需调整子类内部的具体实现细节[^4]。 --- ### 示例总结 综上所述,`super()` 主要用来解决单继承或多继承情况下如何优雅地调用父类成员的问题。它不仅让代码更干净易懂,还增强了系统的扩展能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值