苦练Python第47天:一文吃透继承与多继承,MRO教你不再踩坑

前言

大家好,我是倔强青铜三 。欢迎关注我,微信公众号:倔强青铜三。欢迎点赞、收藏、关注,一键三连!!!

欢迎来到 苦练Python第47天

今天,我们把「继承」这件听起来高大上的事儿拆成 5 根辣条 ------

单继承、方法重写、super 连环call、多继承 MRO、菱形陷阱自救指南。

一口气吃完,你就能写出高手级别的可扩展代码。


🧬 继承的本质:把公共代码薅出来复用

ruby 复制代码
class Animal:               # 父类(基类)
    def __init__(self, name):
        self.name = name
    def speak(self):
        return "???"
ruby 复制代码
class Dog(Animal):          # 子类(派生类)
    def speak(self):
        return f"{self.name}: 汪汪!"
ini 复制代码
>>> d = Dog("旺财")
>>> d.speak()
旺财: 汪汪!

结论:子类自动拥有父类所有公共属性和方法
注意:Python 默认所有方法都是 virtual(C++ 术语),想重写就重写。


🔁 方法重写 & 扩展:子类想加料怎么办?

ruby 复制代码
class Cat(Animal):
    def speak(self):
        base = super().speak()      # 先把父类的结果薅过来
        return f"{base} → 喵喵~"   # 再加点私货
ini 复制代码
>>> c = Cat("咪咪")
>>> c.speak()
??? → 喵喵~

super() 的 3 个用处:

  1. 调用父类被覆盖的方法
  2. 在多重继承链里按 MRO 顺序调用
  3. 避免硬编码父类名,方便重构

🌲 多重继承:一娃多爹,爽还是坑?

ruby 复制代码
class Flyable:
    def fly(self):
        return "I can fly!"

class Bird(Animal, Flyable):   # 逗号分隔,多爹
    pass
less 复制代码
>>> b = Bird("啾啾")
>>> b.speak(), b.fly()
('啾啾: ???', 'I can fly!')

真相:Python 支持无限多继承,但顺序很重要!


🔍 MRO(方法解析顺序):Python 的"族谱算法"

python 复制代码
class A:
    def hi(self): print("A")

class B(A):
    def hi(self): print("B")

class C(A):
    def hi(self): print("C")

class D(B, C):
    pass
python 复制代码
>>> D.__mro__
(<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)

口诀:从左到右,深度优先,留坑不回头
有重叠(菱形继承)时,Python 用 C3 线性化保证每个祖先只出现一次。


💎 菱形陷阱 & super 连环call 自救

错误示范:父类被多次初始化

ruby 复制代码
class Base:
    def __init__(self):
        print("Base init")

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

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

class Bottom(Left, Right):
    def __init__(self):
        Left.__init__(self)
        Right.__init__(self)

>>> Bottom()
Base init
Left init
Base init   # 悲剧:Base 被调了两次
Right init

正确姿势:super() 一条龙

ruby 复制代码
class Base:
    def __init__(self):
        print("Base init")

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

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

class Bottom(Left, Right):
    def __init__(self):
        super().__init__()
        print("Bottom init")

>>> Bottom()
Base init
Right init
Left init
Bottom init

解释:

  • 每个类都调用 super() 交给 MRO 下一棒
  • 整个链条只跑一次,Base 只初始化一次

🧰 工具函数:快速判断血缘

需求 代码
实例是否属于某类 isinstance(obj, cls)
类是否继承某类 issubclass(cls1, cls2)
查看 MRO cls.__mro__help(cls)

🧾 速查表

场景 关键语法/技巧
单继承 class Child(Parent):
重写方法 def method(self): ...
扩展父类 super().method()
多继承 class C(A, B):
避免重复初始化 全部用 super()
查看调用顺序 cls.__mro__

✅ 一句话总结

单继承让代码复用,多继承让功能拼乐高;

牢记 super() + MRO,就能在多重继承的迷宫里不迷路!

感谢阅读!微信公众号:倔强青铜三,点赞、收藏、关注,一键三连,我们下期见!

相关推荐
倔强青铜三2 小时前
为什么Python程序员必须学习Pydantic?从数据验证到API开发的革命性工具
人工智能·python·面试
豌豆花下猫2 小时前
Python 潮流周刊#120:新型 Python 类型检查器对比(摘要)
后端·python·ai
Codebee5 小时前
魔改 OneCode-RAD 实现 LLM 编程:打造自然语言驱动的低代码助手
前端·人工智能·前端框架
默默地离开5 小时前
一篇文章理解HTML常考知识
面试·html
IT_陈寒7 小时前
SpringBoot 3.2新特性实战:这5个隐藏技巧让你的启动速度提升50%
前端·人工智能·后端
CodeWolf9 小时前
面试题之Redis的穿透、击穿和雪崩问题
redis·后端·面试
绝无仅有9 小时前
面试经验之mysql高级问答深度解析
后端·面试·github
绝无仅有9 小时前
Java技术复试面试:全面解析
后端·面试·github
后端小肥肠9 小时前
卷出新高度!字节Seedream 4.0模型真实体验:它真的解决了AI绘画的核心痛点?
人工智能·aigc