大家好,我是正在实战各种 AI 项目的程序员晚枫。
🎬 开篇:为什么你的代码"差点意思"?
你有没有遇到过这样的困惑?
明明功能都实现了,代码也能跑,但总觉得:
- 代码写得很啰嗦,不如别人的简洁
- 自定义类用起来"笨重",不像内置类型那么顺手
- 面试被问到"实现一个支持加法的向量类",不知道从何下手
这不是你技术不行,而是你没掌握 Python 数据模型。
一个真实的对比
看看两种实现向量类的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class VectorV1: def __init__(self, x, y): self.x = x self.y = y def add(self, other): return VectorV1(self.x + other.x, self.y + other.y) def multiply(self, scalar): return VectorV1(self.x * scalar, self.y * scalar) def length(self): return (self.x ** 2 + self.y ** 2) ** 0.5 def to_string(self): return f"Vector({self.x}, {self.y})"
v1 = VectorV1(3, 4) v2 = VectorV1(1, 2) v3 = v1.add(v2) print(v3.to_string())
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class VectorV2: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return f"Vector({self.x}, {self.y})" def __add__(self, other): return VectorV2(self.x + other.x, self.y + other.y) def __mul__(self, scalar): return VectorV2(self.x * scalar, self.y * scalar) def __abs__(self): return (self.x ** 2 + self.y ** 2) ** 0.5
v1 = VectorV2(3, 4) v2 = VectorV2(1, 2) print(v1 + v2) print(v1 * 3) print(abs(v1))
|
第二种方式,就是通过 Python 数据模型实现的。
想象一下,你设计了一个向量类 Vector。你希望它能像数字一样相加、相乘,能打印出友好的字符串表示,能用 len() 获取维度。这些功能不是 Python 自动给你的,而是通过实现特殊方法(也叫魔术方法)来实现的。
🎯 什么是 Python 数据模型?
核心思想:协议优于继承
Python 的数据模型是一套协议和约定,它定义了对象如何与 Python 的其他部分交互。
不同于 Java、C# 需要显式实现接口,Python 采用"鸭子类型":
如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子。
只要你的对象实现了特定的方法,Python 就会"认可"它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class MyList: def __len__(self): return 42
obj = MyList() print(len(obj))
class MyRange: def __init__(self, n): self.n = n self.i = 0 def __iter__(self): return self def __next__(self): if self.i >= self.n: raise StopIteration value = self.i self.i += 1 return value
for i in MyRange(3): print(i)
|
为什么叫"特殊方法"?
特殊方法都用双下划线开头和结尾,所以也叫 dunder methods(double underscore):
__init__ 读作 "dunder init"__len__ 读作 "dunder len"
为什么用双下划线?
为了避免和用户定义的方法冲突。你不用担心自己的 len 方法和 Python 的 __len__ 冲突。
Python 如何调用特殊方法?
关键点:Python 会在特定时机自动调用特殊方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Demo: def __init__(self): print("初始化...") def __repr__(self): print("转换为字符串...") return "Demo()" def __len__(self): print("计算长度...") return 42 def __getitem__(self, key): print(f"获取元素: {key}") return key * 2
d = Demo()
print(d)
print(len(d))
print(d[5])
|
你永远不需要这样写:
1 2 3 4 5 6 7 8 9
| print(d.__repr__()) print(d.__len__()) print(d.__getitem__(5))
print(repr(d)) print(len(d)) print(d[5])
|
📊 特殊方法速查表
创建与销毁
| 方法 | 作用 | 触发场景 |
|---|
__new__ | 创建对象实例 | 创建对象时(在 __init__ 之前) |
__init__ | 初始化对象 | 创建对象时 |
__del__ | 销毁对象 | 垃圾回收时(不推荐依赖) |
字符串表示
| 方法 | 作用 | 触发场景 |
|---|
__repr__ | 官方字符串表示 | repr()、交互式解释器 |
__str__ | 用户友好字符串 | str()、print() |
__format__ | 格式化字符串 | format()、f-string |
__bytes__ | 字节序列 | bytes() |
容器协议
| 方法 | 作用 | 触发场景 |
|---|
__len__ | 长度 | len()、布尔判断 |
__getitem__ | 获取元素 | obj[key]、切片、迭代 |
__setitem__ | 设置元素 | obj[key] = value |
__delitem__ | 删除元素 | del obj[key] |
__contains__ | 成员检测 | value in obj |
__iter__ | 迭代器 | iter()、for 循环 |
__reversed__ | 反向迭代 | reversed() |
数值运算
| 方法 | 作用 | 触发场景 |
|---|
__add__ | 加法 | a + b |
__sub__ | 减法 | a - b |
__mul__ | 乘法 | a * b |
__truediv__ | 除法 | a / b |
__floordiv__ | 整除 | a // b |
__mod__ | 取模 | a % b |
__pow__ | 幂运算 | a ** b |
__neg__ | 负号 | -a |
__abs__ | 绝对值 | abs(a) |
比较运算
| 方法 | 作用 | 触发场景 |
|---|
__eq__ | 等于 | a == b |
__ne__ | 不等于 | a != b |
__lt__ | 小于 | a < b |
__le__ | 小于等于 | a <= b |
__gt__ | 大于 | a > b |
__ge__ | 大于等于 | a >= b |
可调用对象
上下文管理
| 方法 | 作用 | 触发场景 |
|---|
__enter__ | 进入上下文 | with obj as x: |
__exit__ | 退出上下文 | with 块结束时 |
属性访问
| 方法 | 作用 | 触发场景 |
|---|
__getattr__ | 获取不存在的属性 | obj.attr(attr 不存在时) |
__getattribute__ | 获取任意属性 | obj.attr(任何情况) |
__setattr__ | 设置属性 | obj.attr = value |
__delattr__ | 删除属性 | del obj.attr |
🔑 关键协议详解
1. 序列协议:让你的对象像列表一样工作
序列协议只需要实现 __len__ 和 __getitem__ 两个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| class Deck: """一副扑克牌 - 完整的序列协议示例""" ranks = [str(n) for n in range(2, 11)] + list('JQKA') suits = '♠♥♦♣' def __init__(self): self._cards = [ (rank, suit) for suit in self.suits for rank in self.ranks ] def __len__(self): """支持 len() 函数""" return len(self._cards) def __getitem__(self, position): """支持索引和切片""" return self._cards[position]
deck = Deck()
print(len(deck)) print(deck[0]) print(deck[-1]) print(deck[::13]) print(deck[0:5])
for card in deck[:5]: print(card)
print(('A', '♠') in deck)
import random print(random.choice(deck)) print(random.sample(deck, 5))
|
为什么只实现两个方法就能获得这么多功能?
因为 Python 会根据 __getitem__ 自动推断其他行为:
- 切片:传入
slice 对象,__getitem__ 返回新序列 - 迭代:从 0 开始不断调用
__getitem__,直到 IndexError in:遍历比较
2. 数值协议:让你的对象像数字一样运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| import math
class Vector: """二维向量 - 完整的数值协议示例""" def __init__(self, x=0, y=0): self.x = x self.y = y def __repr__(self): """官方字符串表示""" return f'Vector({self.x!r}, {self.y!r})' def __str__(self): """用户友好字符串""" return f'({self.x}, {self.y})' def __abs__(self): """向量长度:abs(v)""" return math.hypot(self.x, self.y) def __bool__(self): """布尔值:零向量为 False""" return bool(abs(self)) def __add__(self, other): """向量加法:v1 + v2""" return Vector(self.x + other.x, self.y + other.y) def __sub__(self, other): """向量减法:v1 - v2""" return Vector(self.x - other.x, self.y - other.y) def __mul__(self, scalar): """标量乘法:v * 3""" return Vector(self.x * scalar, self.y * scalar) def __rmul__(self, scalar): """反向乘法:3 * v""" return self.__mul__(scalar) def __truediv__(self, scalar): """标量除法:v / 3""" return Vector(self.x / scalar, self.y / scalar) def __neg__(self): """负向量:-v""" return Vector(-self.x, -self.y) def __eq__(self, other): """相等比较:v1 == v2""" return self.x == other.x and self.y == other.y
v1 = Vector(3, 4) v2 = Vector(1, 2)
print(v1) print(repr(v1)) print(abs(v1)) print(bool(v1)) print(v1 + v2) print(v1 - v2) print(v1 * 3) print(3 * v1) print(v1 / 2) print(-v1) print(v1 == v2)
v3 = Vector(1, 0) v4 = Vector(0, 1) print(v1 + v2 * 2 - v3)
|
__rmul__ 是什么?
当 3 * v1 执行时:
- Python 先尝试
3.__mul__(v1) - int 不知道如何处理 Vector - 失败后,尝试
v1.__rmul__(3) - Vector 的反向乘法
这就是 Python 的运算符机制:先左后右。
3. 上下文管理协议:让你的对象支持 with 语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| class FileManager: """文件管理器 - 自动处理文件的打开和关闭""" def __init__(self, filename, mode='r'): self.filename = filename self.mode = mode self.file = None def __enter__(self): """进入上下文:打开文件""" print(f"打开文件: {self.filename}") self.file = open(self.filename, self.mode) return self.file def __exit__(self, exc_type, exc_val, exc_tb): """退出上下文:关闭文件""" print(f"关闭文件: {self.filename}") if self.file: self.file.close() return False
with FileManager('test.txt', 'w') as f: f.write('Hello, Python!')
class SafeDBConnection: """安全的数据库连接""" def __init__(self, connection_string): self.connection_string = connection_string self.conn = None def __enter__(self): self.conn = self._connect() return self.conn def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is not None: print(f"发生异常: {exc_val},执行回滚") self.conn.rollback() else: print("正常提交") self.conn.commit() self.conn.close() return False def _connect(self): class MockConnection: def commit(self): pass def rollback(self): pass def close(self): pass return MockConnection()
with SafeDBConnection('mysql://...') as conn: pass
with SafeDBConnection('mysql://...') as conn: raise ValueError("出错了")
|
4. 可迭代协议:让你的对象支持 for 循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| class MyRange: """自定义范围 - 实现 __iter__""" def __init__(self, start, end, step=1): self.start = start self.end = end self.step = step def __iter__(self): """返回一个迭代器""" return MyRangeIterator(self.start, self.end, self.step)
class MyRangeIterator: """迭代器实现""" def __init__(self, start, end, step): self.current = start self.end = end self.step = step def __iter__(self): """迭代器自身也是可迭代的""" return self def __next__(self): """返回下一个元素""" if self.current >= self.end: raise StopIteration value = self.current self.current += self.step return value
for i in MyRange(1, 10, 2): print(i)
class MyRangeV2: """使用生成器实现 - 更简洁""" def __init__(self, start, end, step=1): self.start = start self.end = end self.step = step def __iter__(self): """生成器函数自动返回迭代器""" current = self.start while current < self.end: yield current current += self.step
for i in MyRangeV2(1, 10, 2): print(i)
|
📊 性能对比
__len__ 的性能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import time
class SlowLen: """低效的 __len__ 实现""" def __init__(self, data): self.data = data def __len__(self): count = 0 for _ in self.data: count += 1 return count
class FastLen: """高效的 __len__ 实现""" def __init__(self, data): self.data = data def __len__(self): return len(self.data)
data = list(range(1000000))
slow = SlowLen(data) fast = FastLen(data)
start = time.time() for _ in range(1000): len(slow) print(f"SlowLen: {time.time() - start:.4f}s")
start = time.time() for _ in range(1000): len(fast) print(f"FastLen: {time.time() - start:.4f}s")
|
结论:__len__ 会被频繁调用,务必优化实现。
__getitem__ vs 直接访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import timeit
class DirectAccess: """直接访问内部列表""" def __init__(self, data): self.data = data
class GetItemAccess: """通过 __getitem__ 访问""" def __init__(self, data): self.data = data def __getitem__(self, key): return self.data[key]
data = list(range(10000)) direct = DirectAccess(data) getitem = GetItemAccess(data)
direct_time = timeit.timeit( lambda: direct.data[5000], number=1000000 )
getitem_time = timeit.timeit( lambda: getitem[5000], number=1000000 )
print(f"直接访问: {direct_time:.4f}s") print(f"__getitem__: {getitem_time:.4f}s") print(f"开销: {(getitem_time - direct_time) / direct_time * 100:.1f}%")
|
结论:__getitem__ 有轻微开销,但换来了巨大的灵活性。
🚀 进阶用法
1. __repr__ vs __str__ 深度解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| class Person: """演示 __repr__ 和 __str__ 的区别""" def __init__(self, name, age, email): self.name = name self.age = age self.email = email def __repr__(self): """ 官方字符串表示 目标:无歧义,能用来重建对象 场景:调试、日志、交互式解释器 """ return f"Person(name='{self.name}', age={self.age}, email='{self.email}')" def __str__(self): """ 用户友好字符串 目标:易读,给终端用户看 场景:print()、str()、用户界面 """ return f"{self.name}({self.age}岁)" def __format__(self, format_spec): """ 格式化字符串 支持自定义格式规范 """ if format_spec == 'short': return f"{self.name}({self.age})" elif format_spec == 'full': return f"{self.name}, {self.age}岁, {self.email}" else: return str(self)
p = Person("张三", 30, "zhangsan@example.com")
print(repr(p)) print(str(p)) print(p)
>>> p Person(name='张三', age=30, email='zhangsan@example.com')
print([p, p])
print(f"{p:short}") print(f"{p:full}")
|
最佳实践:
- 总是实现
__repr__,它是最重要的调试工具 __repr__ 应该能 eval() 重建对象(如果可能)__str__ 是可选的,默认会 fallback 到 __repr__
2. 实现 __bool__ 让对象更智能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| class Collection: """集合类 - 支持布尔判断""" def __init__(self, items=None): self.items = items if items is not None else [] def __len__(self): return len(self.items) def __bool__(self): """ 自定义布尔值 默认:空容器为 False,非空为 True """ return len(self) > 0
empty = Collection() full = Collection([1, 2, 3])
if empty: print("有元素") else: print("空集合")
if full: print("有元素")
class Result: """操作结果""" def __init__(self, success, data=None, error=None): self.success = success self.data = data self.error = error def __bool__(self): return self.success def __repr__(self): if self.success: return f"Result(data={self.data})" else: return f"Result(error='{self.error}')"
def divide(a, b): if b == 0: return Result(False, error="除数不能为0") return Result(True, data=a / b)
result = divide(10, 2) if result: print(f"结果: {result.data}")
result = divide(10, 0) if not result: print(f"错误: {result.error}")
|
3. __getitem__ 支持多维索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| class Matrix: """二维矩阵 - 支持多维索引""" def __init__(self, rows, cols): self.rows = rows self.cols = cols self.data = [[0] * cols for _ in range(rows)] def __repr__(self): return f"Matrix({self.rows}x{self.cols})" def __getitem__(self, key): """ 支持多种索引方式: - matrix[i, j]:获取元素 - matrix[i]:获取整行 - matrix[i:j, k:l]:获取子矩阵 """ if isinstance(key, tuple): row, col = key return self.data[row][col] elif isinstance(key, slice): return [row[:] for row in self.data[key]] else: return self.data[key] def __setitem__(self, key, value): if isinstance(key, tuple): row, col = key self.data[row][col] = value else: self.data[key] = value
m = Matrix(3, 3)
m[0, 0] = 1 m[1, 1] = 2 m[2, 2] = 3
print(m[0, 0]) print(m[1]) print(m[0:2])
|
4. 实现 __hash__ 支持作为字典键
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| class Point: """二维点 - 可哈希""" def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return f"Point({self.x}, {self.y})" def __eq__(self, other): if not isinstance(other, Point): return NotImplemented return self.x == other.x and self.y == other.y def __hash__(self): """让对象可哈希,能作为字典键或存入集合""" return hash((self.x, self.y))
p1 = Point(1, 2) p2 = Point(1, 2) p3 = Point(3, 4)
print(p1 == p2) print(p1 is p2)
distances = { Point(0, 0): 0, Point(1, 0): 1, Point(0, 1): 1, }
print(distances[Point(1, 0)])
points = {p1, p2, p3} print(len(points))
|
⚠️ 避坑指南
陷阱 1:可变默认参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class BadExample: def __init__(self, items=[]): self.items = items
a = BadExample() a.items.append(1) print(a.items)
b = BadExample() print(b.items)
class GoodExample: def __init__(self, items=None): self.items = items if items is not None else []
a = GoodExample() a.items.append(1) print(a.items)
b = GoodExample() print(b.items)
|
陷阱 2:忘记调用父类 __init__
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Parent: def __init__(self): self.parent_value = 100
class BadChild(Parent): def __init__(self, value): self.value = value c = BadChild(1) print(c.value) print(c.parent_value)
class GoodChild(Parent): def __init__(self, value): super().__init__() self.value = value
c = GoodChild(1) print(c.value) print(c.parent_value)
|
陷阱 3:__eq__ 破坏了 __hash__
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class BadPoint: def __init__(self, x, y): self.x = x self.y = y def __eq__(self, other): return self.x == other.x and self.y == other.y
p = BadPoint(1, 2)
class GoodPoint: def __init__(self, x, y): self.x = x self.y = y def __eq__(self, other): return self.x == other.x and self.y == other.y def __hash__(self): return hash((self.x, self.y))
p = GoodPoint(1, 2) print(hash(p))
|
规则:如果实现了 __eq__,要么同时实现 __hash__,要么显式设置 __hash__ = None。
陷阱 4:可变对象的 __hash__
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class MutablePoint: def __init__(self, x, y): self.x = x self.y = y def __eq__(self, other): return self.x == other.x and self.y == other.y def __hash__(self): return hash((self.x, self.y))
p = MutablePoint(1, 2) points = {p}
p.x = 3
class SafeMutablePoint: __hash__ = None def __init__(self, x, y): self.x = x self.y = y def __eq__(self, other): return self.x == other.x and self.y == other.y
|
陷阱 5:__getattr__ vs __getattribute__
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class Demo1: def __init__(self): self.x = 1 def __getattr__(self, name): print(f"获取不存在的属性: {name}") return None
d1 = Demo1() print(d1.x) print(d1.y)
class Demo2: def __init__(self): self.x = 1 def __getattribute__(self, name): print(f"获取属性: {name}") return object.__getattribute__(self, name)
d2 = Demo2() print(d2.x) print(d2.y)
class BadDemo: def __init__(self): self.x = 1 def __getattribute__(self, name): return object.__getattribute__(self, name)
|
🎯 实战案例:实现一个完整的扑克牌类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| import random from collections import namedtuple
Card = namedtuple('Card', ['rank', 'suit'])
class FrenchDeck: """法国扑克牌 - 52 张""" ranks = [str(n) for n in range(2, 11)] + list('JQKA') suits = '♠♥♦♣' def __init__(self): self._cards = [ Card(rank, suit) for suit in self.suits for rank in self.ranks ] def __len__(self): return len(self._cards) def __getitem__(self, position): return self._cards[position] def __repr__(self): return f"FrenchDeck({len(self)} cards)" def __bool__(self): return len(self) > 0 def shuffle(self): """洗牌""" random.shuffle(self._cards) return self def deal(self, n=1): """发牌""" if n > len(self): raise ValueError("牌不够了") hand = [self._cards.pop() for _ in range(n)] return hand def sort_by_suit(self): """按花色排序""" self._cards.sort(key=lambda c: self.suits.index(c.suit)) return self def sort_by_rank(self): """按点数排序""" self._cards.sort(key=lambda c: self.ranks.index(c.rank)) return self
deck = FrenchDeck() print(deck) print(len(deck)) print(deck[0]) print(deck[-1])
deck.shuffle() print(deck[:5])
hand = deck.deal(5) print(f"你拿到了: {hand}") print(f"剩余: {len(deck)} 张")
deck.sort_by_rank() print(deck[:5])
for card in deck: if card.rank == 'A': print(card)
from collections import Counter suits = Counter(card.suit for card in deck) print(suits)
|
🎯 本讲总结
通过本讲,我们理解了:
| 知识点 | 核心要点 |
|---|
| 数据模型 | Python 对象交互的协议和约定,"协议优于继承" |
| 特殊方法 | 双下划线方法,Python 在特定时机自动调用 |
| 序列协议 | __len__ + __getitem__,获得切片、迭代等功能 |
| 数值协议 | __add__、__mul__ 等,让对象像数字一样运算 |
| 上下文管理 | __enter__ + __exit__,支持 with 语句 |
| 字符串表示 | __repr__ 调试用,__str__ 用户看 |
| 性能考虑 | __len__ 会被频繁调用,务必优化 |
| 常见陷阱 | 可变默认参数、忘记 super()、破坏 hash |
记住这句话:
Python 数据模型让你写的类能无缝融入 Python 的语法体系,用最少的代码实现最多的功能。
📚 推荐教材
《Python 编程从入门到实践(第 3 版)》 - Eric Matthes 著
Python 零基础入门首选。本书分为基础语法和项目实战两部分,适合完全没有编程经验的读者。
《流畅的 Python(第 2 版)》 - Luciano Ramalho 著
Python 进阶经典之作。深入讲解 Python 的高级特性,包括数据模型、函数式编程、面向对象、元编程等。
《CPython 设计与实现》 - Anthony Shaw 著
本书深入讲解 CPython 内部机制,从内存管理到字节码执行,从对象模型到并发编程。配合本课程学习,效果更佳。
学习路线建议:
1
| 零基础 → 《从入门到实践》 → 《流畅的 Python》 → 本门课程 → 《CPython 设计与实现》
|
🎓 加入《流畅的 Python》直播共读营
学到这里,如果你想系统吃透这本书——欢迎加入我的直播共读课。
- 每周直播精讲,逐章拆解核心知识点
- 专属学习群,随时答疑交流
- 试运营特惠:
499 元 → 299 元
👉 【立即报名《流畅的 Python》共读课】:https://mp.weixin.qq.com/s/ivHJwn1nNx5ug4TFrapvGg
🔗 课程导航
← 课程大纲 | 下一讲:数据容器深度解析 →
💬 联系我
主营业务:AI 编程培训、企业内训、技术咨询
🎓 AI 编程实战课程
想系统学习 AI 编程?程序员晚枫的 AI 编程实战课 帮你从零上手!
