Python魔术方法是类中以双下划线开头和结尾的特殊方法,用于实现协议接口,使自定义类支持运算符、遍历、打印、上下文管理等内置行为;其中__new__负责对象创建,__init__负责初始化,__str__和__repr__分别面向用户和开发者,__add__等支持运算符重载,__enter__/__exit__用于资源管理,而__del__不可靠应避免用于关键清理。
Python魔术方法(Magic Methods),也叫双下划线方法(Dunder Methods),是类中以双下划线开头和结尾的特殊方法,比如 __init__、__str__、__add__。它们不是用来“炫技”的,而是让自定义类能自然融入Python语法体系——支持 + 运算、for遍历、print打印、len()调用、上下文管理等,本质上是**协议接口**,告诉解释器“你的对象想怎么被使用”。
__init__ 负责初始化已创建的对象,它接收的是已经分配好内存的实例;真正负责对象创建(即分配内存)的是 __new__。多数情况下只需重写 __init__,但若需控制实例生成逻辑(如单例、不可变类型、从缓存返回对象),就得干预 __new__。
__new__(cls, ...) 必须返回一个 cls 类型的实例(通常调用 super().__new__(cls))__init__(self, ...) 无返回值,只做属性赋值或状态设置__new__ 返回的不是 cls 实例,__init__ 将不会被调用__str__ 用于 str(obj) 和 print(obj),目标是可读、友好、适合终端用户;__repr__ 用于 repr(obj) 和交互式环境直接输出,强调明确性、无歧义,最好能“复制粘贴运行后重建对象”。
__repr__ 是调试基础,缺省时 Python 会给出类似 <__main__.point object at> 的地址信息__str__ 缺省时自动调用 __repr__,所以务必先实现 __repr__
datetime(2025, 1, 1) 的 __repr__ 是 datetime.datetime(2025, 1, 1, 0, 0),__str__ 是 '2025-01-01 00:00:00'
通过实现对应魔术方法,你的类就能像内置类型一样参与运算。关键不是“能重载”,而是“是否符合直觉”。比如 __add__ 应该返回新对象而非修改自身(除非明确设计为就地操作,此时用 __iadd__)。
__add__(self, other) → a + b;__iadd__(self, other) → a += b
__eq__(self, other) 控制 == 行为;注意:不实现 __eq__ 时默认比较身份(id),实现后 != 自动基于 not ==,除非显式定义 __ne__
__getitem__(self, key) 支持 obj[key];配合 __len__ 和 __iter__ 可让对象支持 for 循环和 in 检查with 语句依赖 __enter__ 和 __exit__,
用于安全获取/释放资源(如文件、锁、数据库连接)。而 __del__ 是析构方法,在对象被垃圾回收前调用,但它**不可靠、不及时、不推荐用于关键资源释放**。
__enter__ 通常返回 self 或所需资源,__exit__ 接收异常三元组,返回 True 可抑制异常__del__ 不保证何时执行(尤其在程序退出时可能跳过),也不能假设其他对象还存在;应优先用 try/finally 或 contextlib.closing
__init__ 或工厂函数,资源释放交由 __exit__ 显式控制掌握魔术方法不是为了堆砌功能,而是让类的行为更自然、更符合 Pythonic 风格。每个方法都有明确的语义契约,破坏它会让使用者困惑。写之前先问:这个操作对我的类来说,是否有公认的、无歧义的含义?