🐍 Day 8:面向对象编程

📌 一句话提纲

Python 的 OOP 从 class 出发,覆盖构造函数、属性管理、方法类型、继承体系与 MRO,以及双下划线魔法方法。


1. 类与实例

基本定义

python 复制代码
class Dog:
    # 类属性(所有实例共享)
    species = "Canis familiaris"

    # 构造函数
    def __init__(self, name: str, age: int):
        self.name = name      # 实例属性
        self.age = age

    # 实例方法
    def bark(self):
        return f"{self.name} says Woof!"
python 复制代码
d1 = Dog("Buddy", 3)
d2 = Dog("Max", 5)
print(d1.name)       # Buddy
print(d1.species)    # Canis familiaris(类属性)
print(d2.species)    # Canis familiaris
Dog.species = "新物种"  # 修改类属性影响所有实例
print(d1.species)    # 新物种

实例属性 vs 类属性陷阱

python 复制代码
class Cat:
    tricks = []

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

    def learn(self, trick):
        self.tricks.append(trick)  # 坑!修改的是类属性,所有实例共享

c1 = Cat("Kitty")
c2 = Cat("Mimi")
c1.learn("roll over")
print(c2.tricks)     # ['roll over'] 😱

# 正确做法
class Cat:
    def __init__(self, name):
        self.name = name
        self.tricks = []  # 实例属性,每个猫独立

    def learn(self, trick):
        self.tricks.append(trick)

避坑: 不要在方法里修改可变类属性(list/dict),要用实例属性。


2. 三种方法类型

python 复制代码
class MyClass:
    class_var = "类变量"

    def __init__(self, value):
        self.value = value

    # ① 实例方法 ------ 第一个参数 self
    def instance_method(self):
        return f"实例方法: {self.value}"

    # ② 类方法 ------ 第一个参数 cls
    @classmethod
    def class_method(cls):
        return f"类方法: {cls.class_var}"

    # ③ 静态方法 ------ 没有 self/cls
    @staticmethod
    def static_method(x, y):
        return x + y
python 复制代码
obj = MyClass(42)
print(obj.instance_method())  # 实例方法: 42
print(MyClass.class_method()) # 类方法: 类变量
print(MyClass.static_method(3, 5))  # 8
类型 装饰器 访问实例 访问类 适用场景
实例方法 操作实例状态
类方法 @classmethod 工厂方法、替代构造器
静态方法 @staticmethod 工具函数,本质上只是放在类命名空间

@classmethod 典型场景:工厂方法

python 复制代码
from datetime import date

class Person:
    def __init__(self, name: str, birth_year: int):
        self.name = name
        self.birth_year = birth_year
        self.age = date.today().year - birth_year

    @classmethod
    def from_birthday(cls, name: str, birthday: str):
        """从生日字符串创建实例(替代构造器)"""
        year = int(birthday.split("-")[0])
        return cls(name, year)

p = Person.from_birthday("Alice", "1995-06-15")
print(f"{p.name}, {p.age}岁")  # Alice, 31岁

3. 继承与 super()

python 复制代码
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        raise NotImplementedError("子类必须实现")

class Cat(Animal):
    def __init__(self, name, color):
        super().__init__(name)  # 调用父类构造
        self.color = color

    def speak(self):
        return f"{self.name} says 喵~"

class Dog(Animal):
    def speak(self):
        return f"{self.name} says 汪!"
python 复制代码
animals = [Cat("小花", "橘色"), Dog("旺财")]
for a in animals:
    print(a.speak())
# 小花 says 喵~
# 旺财 says 汪!

核心规则:

  • 永远用 super().__init__() 调用父类构造,不要写 Parent.__init__(self)
  • 多继承时 super() 保证 MRO 顺序正确

4. MRO(方法解析顺序)

python 复制代码
class A:
    def method(self): return "A"

class B(A):
    def method(self): return "B"

class C(A):
    def method(self): return "C"

class D(B, C):
    pass

print(D.__mro__)
# (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)
print(D().method())  # B(C3 线性化)

MRO 采用 C3 线性化:广度优先 + 保证单调性。

super() 不是 "父类" 而是 "MRO 中的下一个",多继承时极其有用。


5. 私有属性(Name Mangling)

python 复制代码
class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner
        self._internal_id = 123      # 约定"私有",实际上可以访问
        self.__password = "secret"   # Name Mangling → _BankAccount__password

    def get_balance(self):
        return self.__password

acc = BankAccount("Alice", 1000)
print(acc._internal_id)      # 123(能访问但不推荐)
# print(acc.__password)      # ❌ AttributeError
print(acc._BankAccount__password)  # "secret"(知道规则就能访问)
命名 含义 实际行为
name 公开 正常访问
_name 保护(约定) 正常访问,但 IDE 会提示
__name 私有(Name Mangling) 变为 _ClassName__name
__name__ 魔法方法 保留给 Python 特殊方法

6. @property(属性装饰器)

替代 getter/setter 的 Python 方式

python 复制代码
class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius

    @property
    def celsius(self):
        return self._celsius

    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("温度不能低于绝对零度")
        self._celsius = value

    @property
    def fahrenheit(self):
        return self._celsius * 9/5 + 32

t = Temperature(25)
print(t.celsius)       # 25(像访问属性一样)
t.celsius = 30         # 走 setter
print(t.fahrenheit)    # 86.0(计算属性)
# t.celsius = -300     # ❌ ValueError

优点: 外部调用方式不变,内部可以加校验/计算逻辑。


7. 常用特殊方法

python 复制代码
class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages

    def __str__(self):
        return f"《{self.title}》- {self.author}"

    def __repr__(self):
        return f"Book('{self.title}', '{self.author}', {self.pages})"

    def __len__(self):
        return self.pages

    def __eq__(self, other):
        if not isinstance(other, Book):
            return NotImplemented
        return self.title == other.title and self.author == other.author

    def __lt__(self, other):
        return self.pages < other.pages

book1 = Book("Python实战", "张三", 300)
book2 = Book("Python实战", "张三", 300)

print(str(book1))                        # 《Python实战》- 张三
print(repr(book1))                       # Book('Python实战', '张三', 300)
print(len(book1))                        # 300
print(book1 == book2)                    # True
print(book1 < Book("数据结构", "李四", 500))  # True

📝 要点总结

概念 要点
类属性 vs 实例属性 可变对象务必放 __init__
@classmethod 工厂方法/替代构造器的最佳选择
super() 始终用它调用父类构造,支持多继承
MRO C3 线性化,查看用 ClassName.__mro__
__ 私有属性 只是 Name Mangling,不是真正的 private
@property Python 风格的 getter/setter,优雅又安全
特殊方法 __str__ 给人看,__repr__ 给开发者看
相关推荐
程序员天天困17 分钟前
向量检索不准怎么办:混合检索与 Rerank 重排序召回优化实战
后端·python·ai编程
吃饱了得干活17 分钟前
一篇讲清楚Spring Boot:自动装配、启动器、过滤器、拦截器、设计模式
java·spring boot·后端
CodeSheep28 分钟前
OpenJDK 全面禁止 AI 生成代码!
前端·后端·程序员
IT_陈寒1 小时前
为什么我的Vue组件总是莫名其妙重渲染?
前端·人工智能·后端
alphaTao2 小时前
LeetCode 每日一题 2026/8/24-2026/8/30
python·算法·leetcode
苏灿烤鱼2 小时前
当 AI Agent 遇见真实科学环境:深度拆解 Scientific Agent Skills,把"聊天机器人"变成"AI 科学家"
python·开源·agent
张文君2 小时前
ubuntu26.04坏道坏块分区隔离急速版260831-V0.12
linux·python
东风破_9 小时前
danci 2:创建的单词书到底存在哪里?从 Supabase 一路理解 ORM、Drizzle 和 RLS
数据库·后端·node.js