Day 031 — 类与对象:图解
面向对象编程核心概念图、内存布局、特殊方法关系图
1️⃣ 类与对象的关系
┌─────────────────────────────────────────────┐
│ 类 (Class) │
│ ───────── │
│ class Dog: │
│ species = "Canis" │ ← 类变量(共享)
│ │
│ def __init__(self, name): │
│ self.name = name │ ← 实例变量(独立)
│ │
│ def bark(self): │
│ print("Woof!") │ ← 实例方法
└────────────┬────────────────┬───────────────┘
│ │
┌───────┴──────┐ ┌────┴────────┐
│ 对象1 │ │ 对象2 │
│ ───────── │ │ ───────── │
│ name="Buddy"│ │ name="Max" │
│ species │ │ species │
│ (引用类) │ │ (引用类) │
└──────────────┘ └─────────────┘
2️⃣ 属性查找机制
obj.attribute 的查找顺序:
┌──────────┐
│ obj.__dict__│ ← 查找实例属性
└─────┬────┘
找到? ──→ 是 ──→ 返回
│
否
▼
┌──────────┐
│ type(obj). │
│ __dict__ │ ← 查找类属性
└─────┬────┘
找到? ──→ 是 ──→ 返回
│
否
▼
┌───────────┐
│ 父类链 │ ← 逐级查找父类
└─────┬─────┘
找到? ──→ 是 ──→ 返回
│
否
▼
┌───────────┐
│ Attribute │
│ Error │
└───────────┘
示例:
buddy = Dog("Buddy")
buddy.name → 先找 buddy.__dict__ → 找到 "Buddy"
buddy.species → 先找 buddy.__dict__ → 没找到
→ 找 Dog.__dict__ → 找到 "Canis familiaris"
buddy.species = "Mutt" → 创建实例变量
→ 不影响 Dog.species
3️⃣ 内存布局
Python 对象内存布局
──────────────────
┌─────────────────────────────┐
│ 对象头 (Object Header) │
├─────────────────────────────┤
│ PyObject_HEAD │
│ ┌───────────┬─────────────┐ │
│ │ ob_refcnt │ ob_type │ │
│ │ (引用计数) │ (指向类) │ │
│ └───────────┴─────────────┘ │
├─────────────────────────────┤
│ 实例属性 │
│ ╔═════════════════════════╗ │
│ ║ __dict__ (字典) ║ │ ← 存储实例变量
│ ║ 或 __slots__ 定义的属性 ║ │
│ ╚═════════════════════════╝ │
└─────────────────────────────┘
类对象内存布局:
┌─────────────────────────────┐
│ PyObject_HEAD │
├─────────────────────────────┤
│ ╔═════════════════════════╗ │
│ ║ __dict__ ║ │ ← 存储类变量和方法
│ ║ - species ║ │
│ ║ - __init__ ║ │
│ ║ - bark ║ │
│ ╚═════════════════════════╝ │
├─────────────────────────────┤
│ tp_base → 父类 │
│ tp_mro → 方法解析顺序 │
└─────────────────────────────┘
4️⃣ __new__ vs __init__ 流程
x = MyClass(42)
Step 1: __new__
┌────────────────────────┐
│ MyClass.__new__(cls, 42)│
│ │
│ 1. 分配内存 │
│ 2. 创建空实例 │
│ 3. 返回实例 │
└───────────┬────────────┘
│
▼ 实例已创建(属性还未设置)
│
Step 2: __init__
┌────────────────────────┐
│ instance.__init__(42) │
│ │
│ 1. 接收已创建的实例 │
│ 2. 初始化实例属性 │
│ self.value = 42 │
└───────────┬────────────┘
│
▼ 实例准备好了
x = MyClass(42)
x.value → 42
5️⃣ 特殊方法关系图
┌───────────────────┐
│ 特殊方法系统 │
└───────────────────┘
┌──────────────────┐ ┌──────────────────┐
│ 字符串表示 │ │ 比较运算 │
│ __str__ print │ │ __eq__ == │
│ __repr__ repr │ │ __ne__ != │
│ __format__ format │ │ __lt__ < │
└──────────────────┘ │ __le__ <= │
│ __gt__ > │
┌──────────────────┐ │ __ge__ >= │
│ 算术运算 │ └──────────────────┘
│ __add__ + │
│ __sub__ - │ ┌──────────────────┐
│ __mul__ * │ │ 容器行为 │
│ __truediv__ / │ │ __len__ len() │
│ __floordiv__ // │ │ __getitem__ [] │
│ __mod__ % │ │ __setitem__ []= │
│ __pow__ ** │ │ __contains__ in │
│ __neg__ -x │ │ __iter__ for │
└──────────────────┘ └──────────────────┘
┌──────────────────┐ ┌──────────────────┐
│ 类型转换 │ │ 其他 │
│ __int__ int() │ │ __call__ obj() │
│ __float__ float()│ │ __bool__ bool() │
│ __str__ str() │ │ __hash__ hash() │
│ __repr__ repr()│ │ __del__ 删除 │
└──────────────────┘ └──────────────────┘
6️⃣ 图书管理系统架构
┌────────────────────────────────────┐
│ Library │
│ ─────────────────────────── │
│ + books: {isbn: Book} │
│ + members: {id: Member} │
│ + records: [BorrowRecord] │
│ │
│ + add_book() │
│ + borrow_book() │
│ + return_book() │
│ + search_books() │
│ + stats() │
└────────┬───────────┬───────────────┘
│ │
┌───────┴──┐ ┌─────┴────────┐
│ Book │ │ Member │
│ ─────── │ │ ────────── │
│ title │ │ member_id │
│ author │ │ name │
│ isbn │ │ email │
│ genre │ │ borrowed_books
│ pages │ │ max_books │
│ avail. │ │ fine │
│ borrow_count │
└─────────┘ └──────────────┘
│
┌────┴────────┐
│ BorrowRecord│
│ ─────────── │
│ book_isbn │
│ member_name │
│ borrow_date │
│ due_date │
│ return_date │
│ fine │
└─────────────┘
7️⃣ __slots__ 内存对比
普通类(__dict__):
┌────────────────────────────────┐
│ 对象头 │ __dict__ → {...} │
└────────────────────────────────┘
│
┌──────────┴─────────┐
│ {'x': 1, 'y': 2} │ ← 额外字典对象
└────────────────────┘
__slots__ 类:
┌────────────────────────────────┐
│ 对象头 │ x=1 │ y=2 │ ← 直接存储为对象属性
└────────────────────────────────┘
无 __dict__ → 节省内存
对比 (n=100000):
普通: ~560 bytes/对象 → ~56 MB
slots: ~48 bytes/对象 → ~4.8 MB
节省: 约 91% 内存!