python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python多重继承

Python多重继承的使用小结

作者:小鸡吃米…

Python支持多重继承,允许子类继承多个父类的属性和方法,当父类存在同名方法时,Python会按照方法解析顺序(MRO)决定调用顺序,下面就来详细的介绍一下多重继承的使用

继承是面向对象编程中的一个特性,允许类继承另一个类的属性和方法。在 Python 中,你可以实现不同类型的继承,比如单继承、多继承和多层继承。本章详细介绍了多重继承。

什么是多重继承?

多重继承是一种继承方式,其中单个类可以继承多个父类的属性和方法。当你想把多个类的功能整合到一个类里时,这可以用。下图展示了多重继承 −

多重继承的例子

在下面的例子中,子类继承了父类和母类 -

class Father:
    def skill1(self):
        print("Father's skill: Gardening")
 
class Mother:
    def skill2(self):
        print("Mother's skill: Cooking")
 
class Child(Father, Mother):
    pass
 
c = Child()
c.skill1()
c.skill2()

上述代码的输出为−

Father's skill: Gardening
Mother's skill: Cooking

解释:在这个例子中,类可以同时访问其父类的 skill1() 和 skill2() 方法。当我们创建 Child 实例并调用 skill1() 时,它执行的是 Father 类的方法。同样,当我们调用 skill2() 时,它执行的是母类的方法。

但是,如果两个父类都有同名的方法,会发生什么?谁会被处决?这就是方法分辨率次序(MRO)发挥作用的地方。

多重继承的方法解析顺序

如果同名方法在多个父类中定义,Python 会遵循特定的顺序来决定执行哪个方法。该命令被称为方法解析令(MRO)。该阶数由C3线性化算法(也称为MRO)确定。MRO命令如下所示。

多重继承最核心的问题是:当多个父类有同名方法时,子类调用该方法会优先执行哪个父类的?Python 通过MRO(Method Resolution Order,方法解析顺序) 来解决这个问题,遵循 “从左到右、深度优先” 的原则(Python3 中是 C3 算法,本质是优化后的深度优先)。

你可以用mro()方法或__mro__属性检查对象的MRO。例如−

print(Child.mro())

Output:
[<class '__main__.Child'>, <class '__main__.Father'>, <class '__main__.Mother'>, 
<class 'object'>]

示例

在以下示例中,Child 类继承了 Father 和 Mother 类的 skill() 方法,但调用的是 mother's 方法。

class Father:
    def skill(self):
        print("Father's skill: Gardening")

class Mother:
    def skill(self):
        print("Mother's skill: Cooking")

class Child(Father, Mother):
    pass

c = Child()
c.skill()

解释:当技能方法在子类实例c中被调用时,它首先会在子类中查找该方法。由于子类没有技能方法,它会按父类排序(父类,然后是母类)搜索父类,并执行第一个找到的。

上述代码的输出为−

Father's skill: Gardening

在多重继承中使用 super()

super() 函数被子类用于调用父类的方法。如果你在多重继承情况下的方法中使用 super(),它会严格按照 MRO 命令来决定调用哪个方法。

示例

在这个例子中,我们有一个包含四个类的类层级结构:A、B、C 和 D。类 D 继承自 B 和 C,证明了多重继承。

class A:
    def show(self):
        print("Class A")

class B(A):
    def show(self):
        print("Class B")
        super().show()

class C(A):
    def show(self):
        print("Class C")
        super().show()

class D(B, C):
    def show(self):
        print("Class D")
        super().show()

d = D()
d.show()

上述代码的输出为−

Class D
Class B
Class C
Class A

解释:D类的MRO为[D, B, C, A, 对象]。这意味着当某个方法在D实例上被调用时,Python会先在D中寻找该方法,然后是B,再是C,最后是A。因此,“D类”、“B类”、“C类”和“A类”将按该顺序印刷。

多重继承中的钻石问题

钻石问题是多重继承中常见的问题。当两个父类继承同一个基类,而子类继承两个父类时,就会出现这种情况。下图展示了这个场景:

钻石问题导致在继承基类时,该调用哪个方法产生混淆。Python 通过遵循我们之前讨论过的方法解析顺序(mro)来解决这个问题。让我们看看钻石问题的例子 −

示例

下面的代码演示了钻石问题以及Python如何通过MRO解决 −

class A:
    def show(self):
        print("Class A")

class B(A):
    def show(self):
        print("Class B")

class C(A):
    def show(self):
        print("Class C")

class D(B, C):
    pass

d = D()
d.show()

上述代码的输出为−

Class B

解释:D类的MRO命令为[D, B, C, A]。所以,当调用 d.show() 时,它首先在类 D 里查找,但那里没有 show 函数,于是它会去 class B,找到 show 函数并执行它。

多重继承的坑与最佳实践

1. 避免的问题

2. 最佳实践

# Mixin类:仅提供通用功能
class SwimMixin:
    def swim(self):
        print("会游泳")

# 主父类
class Person:
    def eat(self):
        print("会吃饭")

# 子类:主继承Person,辅助继承SwimMixin
class Student(Person, SwimMixin):
    pass

stu = Student()
stu.eat()   # 输出:会吃饭
stu.swim()  # 输出:会游泳

多重继承的利弊

多重继承有若干优缺点 -

优点缺点
提升代码模块化和可复用性。增加了复杂度,可能导致模糊性。
允许将多个类别的功能组合在一起。这可能导致钻石问题。
可以创建复杂的现实关系调试和维护更难。

多重继承是一种面向对象编程的概念,其中来自多个父类的方法可以被子类继承。我们讨论了 Python 如何利用方法解析顺序(MRO)处理多重继承,以及如何使用 super() 函数。钻石问题在多重继承中很常见,但 Python 通过 MRO 解决了这个问题。多重继承的主要缺点是让职业层级结构更复杂且更难理解。

结论

  1. Python 支持多重继承,子类可继承多个父类的属性和方法,写法为 class 子类(父类1, 父类2, ...)
  2. 同名方法的执行顺序遵循 MRO 规则,可通过 __mro__ 查看,默认优先执行左侧父类的方法。
  3. 实际开发中应尽量少用多重继承,推荐 Mixin 模式(辅助功能 + 主继承),保证代码可读性和可维护性。

到此这篇关于Python多重继承的使用小结的文章就介绍到这了,更多相关Python多重继承内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文