Python 继承-super函数


在 Python 的面向对象编程中,继承允许一个类从另一个类中继承特性和行为,而 super() 是一个内置函数,用于调用父类的方法,使得子类可以访问父类的初始化方法或其他方法,从而扩展或修改父类的方法行为。

super() 的基本用法

  1. 调用父类的初始化方法:在子类中 super() 可用于调用父类的构造函数,确保父类的初始化部分也被正确执行。
  2. 方法重载与扩展:当重定义一个在父类中已有的方法时,可使用 super() 去调用父类的方法,继而扩展其功能。
  3. 多重继承中的线性化顺序:super() 会按照方法解析顺序(Method Resolution Order,
    MRO)来寻找合适的父类方法,确保多重继承中的方法调用顺序问题。
class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        print(f"{self.name} makes a sound")

class Dog(Animal):
    def __init__(self, name, breed):
        # 调用父类的 __init__ 方法
        super().__init__(name)
        self.breed = breed
    
    def speak(self):
        # 使用super调用父类的speak方法
        super().speak()
        print(f"{self.name} barks")

# 测试代码
dog = Dog("Buddy", "Golden Retriever")
print(dog.name)    # Outputs: Buddy
print(dog.breed)   # Outputs: Golden Retriever
dog.speak()
# Outputs:
# Buddy makes a sound
# Buddy barks

代码解释

  • 父类 Animal:
  1. __init__ 方法接受一个 name,并将其存储在实例属性中。
  2. speak 方法输出动物会发出的声音。
  • 子类 Dog:
  1. __init__ 方法扩展了父类的初始化,添加了 breed(狗品种)这一额外属性。
  2. 使用 super().__init__(name) 调用父类的初始化方法,确保 name 也被正确赋值。
    重写了 speak 方法,利用 super().speak() 调用父类的 speak 方法,然后添加额外的行为(打印狗的叫声)。

super() 在多重继承中的应用

当面对多重继承时,super() 是一个非常有用的工具,因为它可以依赖 MRO 来正确调用方法。这会变得较为复杂,但 super() 可以简化这一过程,使得代码更为清晰

class Base:
    def __init__(self):
        print("Base init")

class A(Base):
    def __init__(self):
        super().__init__()
        print("A init")

class B(Base):
    def __init__(self):
        super().__init__()
        print("B init")

class C(A, B):
    def __init__(self):
        super().__init__()
        print("C init")

# 实例化 C
c = C()
# Outputs:
# Base init
# B init
# A init
# C init

# C类的MRO:C -> A -> B -> Base
# 所以super()会按照这个顺序调用方法

MRO 顺序

在多重继承中,Python 使用 C3 线性化(C3 superclass linearization)算法来计算 MRO。这个算法遵循以下原则:

  • 子类会先于父类被检查。
  • 如果有多个父类,会根据它们在类定义中出现的顺序进行检查。
  • 第一个满足方法解析规则的类的方法被调用。

对于这个例子,类 C 的 MRO 顺序是:C -> A -> B -> Base。原因如下:

  • C 直接继承自 A 和 B,所以 C 先是 A,然后是 B。

  • 然后检查A的继承链,A直接继承自 Base,所以添加 Base。

  • 最后是 B 的继承链,已经在 A 中考虑 Base,因此不会重复。

这样得到了以下 MRO 顺序:
C -> A -> B -> Base

执行顺序

在创建 C 的实例时,调用顺序为:

  1. C.__init__() 调用 super().__init__(),根据 MRO,转到 A.__init__()。
  2. A.__init__() 调用 super().__init__(),根据 MRO,继续转到 B.__init__()。
  3. B.__init__() 调用 super().__init__(),根据 MRO,转到 Base.__init__()
  4. Base.__init__() 运行,打印 “Base init”。
  5. 返回到 B.__init__(), 打印 “B init”。
  6. 返回到 A.__init__(), 打印 “A init”。
  7. 返回到 C.__init__(), 打印 “C init”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值