1. 什么是魔法方法
魔法方法是指前后都有双下划线的特殊方法,例如 init、new、str 等。这些方法是 Python 内部预定义的,将它们以特定名字命名,是为了配合 Python 的特性(如对象创建、属性访问、运算符重载等)实现自定义行为。
2. 常见魔法方法类别与功能
a) 对象的构造与销毁
魔法方法 |
作用描述 |
常用场景 |
__new__ |
实例创建,返回一个新对象 |
单例、元类、自定义创建流程 |
__init__ |
实例初始化,设置属性等 |
常规对象初始化 |
__del__ |
实例删除前调用(析构函数) |
资源释放、日志等 |
b) 字符串与可打印表现
魔法方法 |
作用描述 |
常用场景 |
__str__ |
str(obj)、print(obj) 时的表现 |
用户友好信息 |
__repr__ |
repr(obj)、调试器、解释器中直接输入对象时的表现 |
开发调试、复现对象 |
c) 运算符重载
使实例自定义如何参与各种运算:
魔法方法 |
覆盖的运算符 |
例子 |
__add__ |
+ |
a + b |
__sub__ |
- |
a - b |
__mul__ |
* |
a * b |
__truediv__ |
/ |
a / b |
__floordiv__ |
// |
a // b |
__mod__ |
% |
a % b |
__pow__ |
** |
a ** b |
__eq__ |
== |
a == b |
__ne__ |
!= |
a != b |
__lt__ |
< |
a < b |
__gt__ |
> |
a > b |
__le__ |
<= |
a <= b |
还有很多,比如逻辑运算(__and__
, __or__
等)、反向运算(如 __radd__
)等。
d) 集合与映射接口
用于容器类的自定义:
魔法方法 |
作用描述 |
使用方式 |
__len__ |
求长度 |
len(obj) |
__getitem__ |
获取指定元素 |
obj[key] |
__setitem__ |
设置值 |
obj[key]=value |
__delitem__ |
删除项 |
del obj[key] |
__contains__ |
in/not in 查询 |
item in obj |
__iter__ |
返回迭代器 |
for x in obj |
__next__ |
迭代器的下一个值 |
next(iterator) |
e) 上下文管理
魔法方法 |
作用描述 |
使用方式 |
__enter__ |
进入上下文、with块前调用 |
with obj as xxx |
__exit__ |
离开上下文、with块后调用 |
f) 可调用对象相关
魔法方法 |
作用描述 |
示例 |
__call__ |
让实例像函数一样可调用 |
obj() |
g) 其他常用魔法方法
__getattr__
/ __setattr__
/ __delattr__
:属性访问/设置/删除拦截。
__slots__
:限制对象可以有哪些属性,提高内存效率。
3. 魔法方法功能对比表
方法 |
调用时机/作用 |
返回值须 |
是否常用 |
__new__ |
创建对象(类->实例) |
实例 or 其子类 |
部分场景 |
__init__ |
初始化对象 |
None |
常用 |
__del__ |
删除对象时 |
None |
偶尔 |
__str__ |
str/print |
str |
常用 |
__repr__ |
repr(),交互式解释器 |
str |
常用 |
__add__ |
a+b |
任意 |
按需 |
__getitem__ |
obj[key] |
任意 |
按需 |
__call__ |
obj() |
任意 |
有趣/高阶 |
__enter__ |
with 块开始 |
任意 |
按需 |
__exit__ |
with 块结束 |
None/Bool |
按需 |
4. 总结
- 魔法方法本质上让我们可以“像内置类型一样”自定义自己的类行为。
- 它们不需要显式调用,由 Python 语法环境/运算符/函数自动调用。
- 合理地使用魔法方法,可以让自己的类表现得更“Pythonic”,增加灵活性、可读性与可用性。
- 不是所有魔法方法都需要重写,按需选择。
举例说明:
1 2 3 4 5 6 7 8 9 10 11 12
| class Vector2D: def __init__(self, x, y): self.x, self.y = x, y def __add__(self, other): return Vector2D(self.x + other.x, self.y + other.y) def __str__(self): return f"({self.x}, {self.y})"
v1 = Vector2D(1,2) v2 = Vector2D(3,4) print(v1 + v2) print(str(v1))
|