一、多继承

核心概念:一个子类可以同时继承多个父类的属性和方法。

基本格式

class 子类(父类1, 父类2, ...):
    pass

基础示例(能力组合)

class RobotMove:
    def move(self):
        print("移动")

class RobotSpeak:
    def speak(self):
        print("说话")

class RobotWork:
    def work(self):
        print("工作")

class Robot(RobotMove, RobotSpeak, RobotWork):
    def serve(self):
        self.move()
        self.speak()
        self.work()

robot = Robot()
robot.move()    # 移动
robot.speak()   # 说话
robot.work()    # 工作

二、菱形问题与MRO

菱形问题:当B和C都继承了A,D又继承B和C时,D调用A的方法到底走哪条路?

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

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

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

class D(B, C):
    pass

d = D()
d.show()  # B(按MRO顺序,B在C前面)

MRO(方法解析顺序):Python解决菱形问题的规则。

  • 顺序优先:括号里先写的父类优先级更高
  • 查看方式:类名.mro()类名.__mro__
print(D.mro())  # D -> B -> C -> A -> object

调整继承顺序改变结果

class D(C, B):  # C在前
    pass

d = D()
d.show()  # C(因为C在MRO中排在B前面)

三、super() 在多继承中的作用

核心理解super() 不是调用“父类”,而是按MRO顺序调用下一个类的方法。

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

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

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

class D(B, C):
    pass

d = D()
d.show()
# 输出:A -> C -> B
# 流程:D.show() -> B.show() -> C.show() -> A.show()
# 回到C打印C -> 回到B打印B

执行流程解析

  1. D没有show,按MRO找B
  2. B的show调用super(),按MRO找C
  3. C的show调用super(),按MRO找A
  4. A打印"A",返回C打印"C",返回B打印"B"

四、多继承使用建议

  1. 避免多继承:能用“组合”替代就不用继承。
  2. 明确继承顺序:必须用多继承时,先用mro()确认查找顺序。
  3. 拆分单一职责父类:每个父类只负责一个功能(如Move只处理移动)。
  4. 避免菱形继承:不要设计多层嵌套的多继承结构。

组合替代多继承示例

class ServiceRobot:
    def __init__(self):
        self.movable = Movable()
        self.speakable = Speakable()
        self.workable = Workable()

    def serve(self):
        self.movable.move()
        self.speakable.speak()
        self.workable.work()

五、方法重写

核心概念:子类定义与父类同名的方法,覆盖父类逻辑,实现“个性化”行为。

基础示例

class Shape:
    def area(self):
        print("计算形状的面积")

class Circle(Shape):
    def area(self):
        print("计算圆形的面积")

c = Circle()
c.area()  # 计算圆形的面积

重写时调用父类原方法(super())

class Circle(Shape):
    def area(self):
        super().area()           # 调用父类方法
        print("计算圆形的面积")   # 扩展自己的逻辑

c = Circle()
c.area()
# 输出:计算形状的面积 -> 计算圆形的面积

重写构造方法(init

class User1:
    def __init__(self, name, age):
        self.name = name
        self.age = age

class User(User1):
    def __init__(self, name, age, sex):
        super().__init__(name, age)   # 必须先初始化父类属性
        self.sex = sex

user = User("张三", 12, '男')
print(user.name, user.age, user.sex)  # 张三 12 男

参数灵活处理

class User1:
    def say_hello(self, name):
        print(f"{name}")

class User(User1):
    def say_hello(self, name, sex="子类"):
        print(f"{sex}, {name}")

u = User()
u.say_hello("你好")           # 子类, 你好
u.say_hello("你好", "自定义") # 自定义, 你好

六、方法重写 vs 方法重载

特性 方法重写(Override) 方法重载(Overload)
定义 子类重写父类同名方法 同一类中多个同名但参数不同的方法
Python支持 完全支持 不原生支持(可用默认参数模拟)
核心目的 实现多态,子类个性化 灵活处理不同参数

模拟方法重载

class Calculator:
    def add(self, a, b, c=None):
        if c is None:
            return a + b
        return a + b + c

calc = Calculator()
print(calc.add(1, 2))       # 3
print(calc.add(1, 2, 3))    # 6

七、类属性与私有方法

1. 类的私有属性

用双下划线 __ 开头定义,外部不能直接访问。Python会进行名称改编,变成 _类名__属性名

class User:
    def __init__(self, name, age, sex):
        self.name = name        # 公开属性
        self._age = age         # 保护属性(约定)
        self.__sex = sex        # 私有属性

    def show(self):
        print(f"姓名:{self.name}, 年龄:{self._age}, 性别:{self.__sex}")

p1 = User("张三", 18, "男")
print(p1.name)                    # 可访问
print(p1._age)                    # 可访问但不建议
# print(p1.__sex)                 # 报错!
print(p1._User__sex)              # 通过名称改编访问(不推荐)
2. 类的私有方法

用双下划线 __ 开头定义,只能在类内部通过 self 调用,外部无法直接调用。

class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):          # 公开方法
        self.__check_age()   # 内部调用私有方法

    def __check_age(self):   # 私有方法
        if self.age < 18:
            print(f"{self.name}未满18岁")
        else:
            print(f"{self.name}已满18岁")

p1 = User("张三", 16)
p1.show()                    # 张三未满18岁
# p1.__check_age()           # 报错!

私有方法的适用场景:类内部的辅助逻辑、不想对外暴露的核心逻辑。

3. self 参数详解
  • self 是实例方法的第一个参数,代表当前对象实例
  • 调用时Python自动传入,无需手动传参
  • self 不是关键字,可改为其他名字,但约定用 self
  • 核心作用:通过 self.属性名 访问/修改当前实例的属性,实现不同实例的数据隔离
class User:
    def show(self):   # self 必须写
        print(f"姓名:{self.name}")

    def get_name(this):   # 可改名为 this(不推荐)
        return this.name

八、类的专有方法(魔术方法)

核心概念:以 __ 开头结尾的特殊方法,由Python自动触发,让自定义类支持内置操作。

核心专有方法速查表

方法名 触发场景 核心作用
__init__ 创建实例时 初始化实例属性(构造方法)
__str__ print(实例) / str(实例) 定义友好字符串展示
__repr__ 交互式环境 / repr(实例) 定义调试字符串
__add__ 实例 + 实例 重载加法运算符
__sub__ 实例 - 实例 重载减法运算符
__len__ len(实例) 定义长度逻辑
__getitem__ 实例[索引] 支持索引访问
__setitem__ 实例[索引] = 值 支持索引赋值
__del__ 实例被销毁时 清理资源(析构方法)
__eq__ 实例 == 实例 定义相等判断逻辑

实用示例(索引访问)

class BookShelf:
    def __init__(self, books):
        self.books = books

    def __getitem__(self, index):
        return self.books[index]

    def __setitem__(self, index, value):
        self.books[index] = value

shelf = BookShelf(["Python", "Java", "C++"])
print(shelf[0])         # Python(触发 __getitem__)
shelf[1] = "JavaScript" # 触发 __setitem__
print(shelf.books)      # ['Python', 'JavaScript', 'C++']

今日核心总结

  1. 多继承

    • 子类可继承多个父类,继承顺序决定MRO优先级
    • 菱形问题用MRO解决,用 mro() 查看顺序
    • super() 按MRO顺序调用下一个类的方法
    • 优先用组合替代多继承
  2. 方法重写

    • 子类覆盖父类同名方法,实现个性化逻辑
    • 重写 __init__ 必须调用 super().__init__()
    • super().方法名() 复用父类逻辑
  3. 私有属性与方法

    • __属性名:私有属性,外部不可直接访问(名称改编)
    • __方法名:私有方法,只能在类内部调用
    • Python通过“约定”而非强制实现私有
  4. 专有方法(魔术方法)

    • __xxx__ 格式,Python自动触发
    • 让自定义类支持内置操作(打印、索引、运算等)
    • 最常用:__init____str____getitem__

注:已经使用DeepSeek进行整理精简核心内容,些许不理解的配合个人笔记进行理解。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐