文章目录
-
-
-
- [1. 构造与初始化 (最基础)](#1. 构造与初始化 (最基础))
- [2. 字符串表示 (打印与调试)](#2. 字符串表示 (打印与调试))
- [3. 模拟容器行为 (让对象像列表/字典)](#3. 模拟容器行为 (让对象像列表/字典))
- [4. 运算符重载 (让对象支持数学运算)](#4. 运算符重载 (让对象支持数学运算))
- [5. callable 对象 (让对象像函数一样被调用)](#5. callable 对象 (让对象像函数一样被调用))
- [6. 上下文管理器 (用于 with 语句)](#6. 上下文管理器 (用于 with 语句))
- [7. 属性访问控制 (高级)](#7. 属性访问控制 (高级))
-
-
先声明一点,魔术方法以双下划线命名,但是双下划线命名的不一定就是魔术方法,还可能是内置属性,如 __main__。
1. 构造与初始化 (最基础)
| 方法 | 作用 | 调用时机 |
|---|---|---|
__new__(cls, ...) |
真正创建实例的方法。返回新对象。 | 在 __init__ 之前调用,用于控制实例创建(如单例模式)。 |
__init__(self, ...) |
初始化实例。设置属性。 | 对象创建后立即调用(最常用)。 |
__del__(self) |
析构方法。 | 对象被垃圾回收前调用(通常不推荐依赖它做资源清理)。 |
代码:
python
class Demo:
def __new__(cls):
print("1. 创建对象")
return super().__new__(cls)
def __init__(self):
print("2. 初始化对象")
2. 字符串表示 (打印与调试)
| 方法 | 作用 | 调用时机 |
|---|---|---|
__str__(self) |
给用户看的字符串。 | 使用 print(obj) 或 str(obj) 时。 |
__repr__(self) |
给开发者看的字符串(调试用)。 | 在交互式命令行输入 obj 或 repr(obj) 时。 |
__format__(self, spec) |
自定义格式化。 | 使用 f"{obj:.2f}" 等格式字符串时。 |
最佳实践:repr 应该尽量返回能重现对象的代码(如 <Person('Alice', 20)>),而 str 应该是易读的文本(如 Alice, 20岁)。
3. 模拟容器行为 (让对象像列表/字典)
让你的类支持索引、长度计算和迭代。
python
方法 | 作用 | 对应操作
:--- | :--- | :---
`__len__(self)` | 返回长度。 | `len(obj)`
`__getitem__(self, key)` | 获取元素。 | `obj[key]`
`__setitem__(self, key, value)` | 设置元素。 | `obj[key] = value`
`__delitem__(self, key)` | 删除元素。 | `del obj[key]`
`__contains__(self, item)` | 检查是否存在。 | `item in obj`
`__iter__(self)` | 返回迭代器。 | `for x in obj:` (开始迭代)
`__next__(self)` | 返回下一个值。 | 迭代过程中自动调用
代码:
python
class MyList:
def __init__(self):
self.data = [1, 2, 3]
def __len__(self):
return len(self.data)
def __getitem__(self, index):
return self.data[index]
l = MyList()
print(len(l)) # 调用 __len__ -> 3
print(l[0]) # 调用 __getitem__ -> 1
4. 运算符重载 (让对象支持数学运算)
让你的对象可以使用 +, -, *, > 等符号。
算术运算
python
| 方法 | 操作 | 方法 | 操作 |
| :--- | :--- | :--- | :--- |
| `__add__(self, other)` | `a + b` | `__sub__(self, other)` | `a - b` |
| `__mul__(self, other)` | `a * b` | `__truediv__(self, other)` | `a / b` |
| `__floordiv__(self, other)` | `a // b` | `__mod__(self, other)` | `a % b` |
| `__pow__(self, other)` | `a b` | | |
比较运算
| 方法 | 操作 | 方法 | 操作 |
|---|---|---|---|
__eq__(self, other) |
a == b |
__ne__(self, other) |
a != b |
__lt__(self, other) |
a < b |
__le__(self, other) |
a <= b |
__gt__(self, other) |
a > b |
__ge__(self, other) |
a >= b |
代码:
python
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # 调用 __add__ -> Vector(4, 6)
print(v1 == v2) # 调用 __eq__ -> False
5. callable 对象 (让对象像函数一样被调用)
| 方法 | 作用 | 对应操作 |
|---|---|---|
__call__(self, ...) |
让实例可以像函数一样执行。 | obj() |
代码:
python
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, value):
return value * self.factor
double = Multiplier(2)
print(double(5)) # 输出 10,就像调用函数 double(5)
6. 上下文管理器 (用于 with 语句)
让你的类支持 with open(...) as f: 这种语法,自动管理资源(如文件关闭、锁释放)。
| 方法 | 作用 |
|---|---|
__enter__(self) |
进入 with 块时执行,返回值赋给 as 后面的变量。 |
__exit__(self, exc_type, exc_val, exc_tb) |
离开 with 块时执行(无论是否发生异常)。 |
代码:
python
class MyResource:
def __enter__(self):
print("资源打开")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("资源关闭")
# 返回 True 可以吞掉异常,返回 False (或 None) 则抛出异常
with MyResource() as res:
print("正在使用资源")
7. 属性访问控制 (高级)
拦截对属性的读取、设置和删除操作。
| 方法 | 作用 |
|---|---|
__getattr__(self, name) |
当访问不存在的属性时触发。 |
__setattr__(self, name, value) |
每次设置任何属性时都触发(小心死循环)。 |
__getattribute__(self, name) |
每次访问任何属性时都触发(优先级最高,慎用)。 |
__delattr__(self, name) |
删除属性时触发。 |
总结:什么时候用?
日常开发:最常用的是 init , str , repr , eq 。
数据结构开发:常用 len , getitem , iter 。
数学/科学计算库:大量使用运算符重载 (add , mul 等)。
框架/库开发:常用 call , enter , exit , getattr。