【类的多继承】

目录

代码解释

1. 类的定义

2. 实例化与方法调用

同类案例及结果输出

输出结果

案例解释

多继承

多继承的基本语法

方法解析顺序(MRO)

super () 函数的使用

注意事项

多继承

1. 方法解析顺序(MRO)

2. 同名方法的继承规则

示例 1:简单多重继承

示例 2:调整继承顺序

3. 父类存在共同祖先

示例:共同祖先的 MRO

4. 协作式多重继承与 super()

示例:super() 的链式调用

5. 总结

6. 最佳实践


class Horse:
    def __init__(self, name):
        self.name = name

    def show_info(self):
        return "马的名字{0}".format(self.name)

    def run(self):
        print("马跑了.....")


class Donkey:
    def __init__(self, name):
        self.name = name

    def show_info(self):
        return f"驴的名字{self.name}"

    def run(self):
        print("驴跑了.....")

    def roll(self):
        print("驴打滚......")

# 继承的优先级是从左到右,私有变量无法继承
class Musle(Horse, Donkey):
    def __init__(self, name, age):
        super().__init__(name)
        self.age = age


m = Musle("小驴", 3)

m.run()
m.roll()
print(m.show_info())

代码解释

1. 类的定义
  • Horse 类

    • __init__ 方法:这是构造函数,当创建 Horse 类的实例时,会接收一个参数 name,并将其赋值给实例变量 self.name,用于表示马的名字。
    • show_info 方法:使用 str.format() 方法返回一个格式化的字符串,其中包含马的名字。
    • run 方法:打印一条信息,表示马正在奔跑。
  • Donkey 类

    • __init__ 方法:同样是构造函数,接收一个参数 name,并将其赋值给实例变量 self.name,用于表示驴的名字。
    • show_info 方法:使用 f - 字符串返回一个包含驴名字的字符串。
    • run 方法:打印一条信息,表示驴正在奔跑。
    • roll 方法:打印一条信息,表示驴正在打滚。
  • Musle 类

    • 继承关系Musle 类继承自 Horse 和 Donkey,这是多继承的体现。在 Python 中,多继承时,继承顺序从左到右,即 Horse 的优先级高于 Donkey
    • __init__ 方法:调用 super().__init__(name) 来调用父类的构造函数。由于继承顺序,这里调用的是 Horse 类的 __init__ 方法来初始化 name 属性。同时,为 Musle 类的实例添加了一个新的属性 self.age,用于表示骡子的年龄。
2. 实例化与方法调用
  • m = Musle("小驴", 3):创建 Musle 类的一个实例 m,名字为 "小驴",年龄为 3
  • m.run()Musle 类本身没有定义 run 方法,Python 会按照继承顺序查找。由于 Horse 类在 Donkey 类之前,所以会调用 Horse 类的 run 方法,输出 马跑了.....
  • m.roll()Horse 类中没有 roll 方法,Python 会继续在 Donkey 类中查找,因此调用 Donkey 类的 roll 方法,输出 驴打滚......
  • print(m.show_info())Musle 类没有定义 show_info 方法,按照继承顺序,会调用 Horse 类的 show_info 方法,输出 马的名字小驴

同类案例及结果输出

​
class Bird:
    def __init__(self, name):
        self.name = name

    def show_info(self):
        return f"鸟的名字是 {self.name}"

    def fly(self):
        print(f"{self.name} 在空中飞翔")


class Fish:
    def __init__(self, name):
        self.name = name

    def show_info(self):
        return f"鱼的名字是 {self.name}"

    def swim(self):
        print(f"{self.name} 在水里游动")


class FlyingFish(Bird, Fish):
    def __init__(self, name, color):
        super().__init__(name)
        self.color = color


# 创建实例
ff = FlyingFish("小飞", "银色")

# 调用方法
ff.fly()
ff.swim()
print(ff.show_info())

​

输出结果
小飞 在空中飞翔
小飞 在水里游动
鸟的名字是 小飞
案例解释
  • Bird 类:定义了鸟的基本属性和行为,包括名字和飞翔的能力。
  • Fish 类:定义了鱼的基本属性和行为,包括名字和游泳的能力。
  • FlyingFish 类:继承自 Bird 和 Fish,表示飞鱼。在 __init__ 方法中,调用 super().__init__(name) 初始化名字,并添加了 color 属性。
  • 方法调用
    • ff.fly():调用 Bird 类的 fly 方法,输出 小飞 在空中飞翔
    • ff.swim()Bird 类中没有 swim 方法,调用 Fish 类的 swim 方法,输出 小飞 在水里游动
    • print(ff.show_info()):按照继承顺序,调用 Bird 类的 show_info 方法,输出 鸟的名字是 小飞

多继承

在 Python 中,当一个类继承多个父类且父类中有相同方法时,主要涉及多继承和方法解析顺序(MRO)的概念,以下是具体介绍:

多继承的基本语法

在 Python 中,一个类可以继承自多个父类,语法如下:

class Parent1:
    def method(self):
        print("Parent1's method")

class Parent2:
    def method(self):
        print("Parent2's method")

class Child(Parent1, Parent2):
    pass

这里Child类继承了Parent1Parent2两个父类。

方法解析顺序(MRO)

当多个父类中有相同方法时,Python 使用 C3 线性化算法来确定方法解析顺序。MRO 遵循以下原则:

  • 本地优先:在同一个层次中,优先查找当前类的定义,如果当前类中定义了该方法,则调用当前类的方法。
  • 深度优先:从左到右依次遍历父类,并对每个父类递归地应用同样的规则。

例如:

class A:
    def method(self):
        print("method in class A")

class B(A):
    def method(self):
        print("method in class B")

class C(A):
    def method(self):
        print("method in class C")

class D(B, C):
    pass

d = D()
d.method()  

输出结果是method in class B,因为在 MRO 中,D类的查找顺序是D -> B -> C -> A,所以优先调用了B类中的方法。

super () 函数的使用

在多继承中,可以使用super()函数来调用父类的方法,它会按照 MRO 顺序来调用父类的方法。例如:

class Parent1:
    def method(self):
        print("Parent1's method")

class Parent2:
    def method(self):
        print("Parent2's method")

class Child(Parent1, Parent2):
    def method(self):
        print("Child's method")
        super().method()  

c = Child()
c.method()  

这里Child类重写了method方法,并在其中使用super().method()调用了父类的method方法,会根据 MRO 顺序调用Parent1类的method方法。

注意事项

  • 检查 MRO:可以使用类名.mro()方法来查看类的 MRO 顺序,帮助理解方法调用的优先级。
  • 避免复杂继承:虽然 Python 支持多继承,但过度使用多继承可能会使代码难以理解和维护,尽量保持继承关系简单清晰。
  • 谨慎处理菱形继承:如果存在菱形继承(即一个类通过不同路径继承同一个类),确保所有父类的方法命名清晰,并合理使用super()函数来避免冲突。

多继承

在Python中,当子类继承多个父类且这些父类中存在同名方法时,方法解析顺序(MRO)决定了具体调用哪个方法。以下是详细解释和示例:


1. 方法解析顺序(MRO)

Python使用 C3线性化算法 确定继承顺序,其核心规则是:

  • 子类优先于父类。

  • 继承列表中靠左的父类优先于靠右的父类。

  • 同一父类在继承链中只出现一次。

可以通过 类名.__mro__ 或 类名.mro() 查看类的继承顺序。


2. 同名方法的继承规则

当多个父类有同名方法时,继承顺序由子类定义时父类的排列顺序决定:

  • 左侧父类的方法优先调用

  • 若父类之间存在继承关系(如共同祖先),则按广度优先原则处理。

示例 1:简单多重继承
class A:
    def method(self):
        print("A的method")

class B:
    def method(self):
        print("B的method")

class C(A, B):  # 继承顺序:A在左,B在右
    pass

obj = C()
obj.method()  # 输出:A的method(左侧父类优先)
print(C.__mro__)  # 输出:(C, A, B, object)
示例 2:调整继承顺序
class C(B, A):  # 继承顺序:B在左,A在右
    pass

obj = C()
obj.method()  # 输出:B的method
print(C.__mro__)  # 输出:(C, B, A, object)

3. 父类存在共同祖先

若父类继承自同一个基类,Python会合并继承链,避免重复访问。

示例:共同祖先的 MRO
class D:
    def method(self):
        print("D的method")

class A(D):
    def method(self):
        print("A的method")

class B(D):
    def method(self):
        print("B的method")

class C(A, B):  # 继承顺序:A -> B -> D
    pass

obj = C()
obj.method()  # 输出:A的method
print(C.__mro__)  # 输出:(C, A, B, D, object)

4. 协作式多重继承与 super()

super() 根据 MRO 顺序依次调用父类方法,常用于实现协作式继承。

示例:super() 的链式调用
class A:
    def method(self):
        print("A的method")
        super().method()  # 调用下一个类的方法

class B:
    def method(self):
        print("B的method")
        super().method()

class C(A, B):
    def method(self):
        print("C的method")
        super().method()

obj = C()
obj.method()

输出

C的method
A的method
B的method

MRO顺序C -> A -> B -> object

  • C 的 super() 调用 A 的 method

  • A 的 super() 调用 B 的 method

  • B 的 super() 调用 object 的方法(无输出)。


5. 总结

场景规则
简单多重继承左侧父类的方法优先调用。
父类有共同祖先按广度优先原则合并继承链,避免重复访问。
使用 super()按 MRO 顺序依次调用父类方法,实现协作式继承。
强制调用指定父类方法直接通过父类名调用,如 ParentClass.method(self)

6. 最佳实践

  1. 明确继承顺序:通过合理排列父类顺序,控制同名方法的调用优先级。

  2. 避免菱形继承:减少复杂继承结构,优先使用组合替代多重继承。

  3. 利用 super():在需要协作式继承时,使用 super() 保持代码灵活性。

# 强制调用右侧父类的方法(不推荐,破坏封装)
class C(A, B):
    def call_b_method(self):
        B.method(self)  # 直接指定调用B的方法

obj = C()
obj.call_b_method()  # 输出:B的method

通过理解 MRO 和 super() 的行为,可以更好地设计和管理复杂的类继承关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值