← 返回 Day 31 正文

Day 31 · 图解

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% 内存!