Python魔法方法
本文最后更新于 2025年12月6日 晚上
Python 中的魔法方法是指以双下划线开头和结尾的特殊方法,比如 __init__ 、 __abs__ 等。
Python 中的内置类定义了非常多的魔法方法。
使用dir(o)函数能够快速获知对象所有的方法
魔法方法可以直接被调用,但更多的时候,它会在特定情况下被自动调用。
类
构造和析构
__new__(cls, *args, **kwargs)
__init__(self, *args, **kwargs)
1 | |
__del__(self)
元类
- Python 解析到 class 定义语句。
- 确定该类的元类(默认是 type)。
- 调用元类的 prepare 方法,获取一个空的命名空间对象。
- 执行类体中的代码(如定义方法、赋值属性等),将结果存入这个命名空间。
- 调用元类的 new 方法,传入类名、基类、命名空间等参数,创建类对象。
- 调用元类的 init 方法,初始化类对象。
属性访问
__getattr__(self, attr_name):在实例中找不到属性时调用。__getattribute__(self, attr_name):无论是否找到属性均调用。__setattr__(self, attr_name, attr_value):对属性赋值时调用。__delattr__(self, attr_name):删除属性时调用。
默认情况下对属性的操作都直接作用于self.__dict__上,即使重载了上述方法,最终还是要操作__dict__的,实现这些函数相当于在此之前做一些前置逻辑。
描述符
容器
__getitem__(self, index)
__setitem__(self, key, value)
__delitem__(self, key)
__contains__(self, ele)
实现了此方法就能应用in操作符
__len__(self)
__hash__(self)
与之紧密相关的还有__eq__函数,在set、dict或者frozenset的键判断两个对象是否相等,使用的逻辑是: obj1.__hash__() == obj.__hash__() and (obj1.id() == obj.id() or obj1.__eq__(obj2))
实际开发时如果真的想实现一些自定义的容器类,建议还是直接继承collections.abc包下的基础容器,这样能确保你实现必要的函数。
上下文管理
__enter__(self)__exit__(self)
迭代器
__iter__(self)__next(self)
类型转换
__bool__(self)
__int__(self)
__float__(self)
__str__(self)
__bytes__(self)
一元操作符
__pos__(self)
__neg__(self)
__invert__(self)
分别表示+、-和~
__complex__:实现内建函数complex(),取复数。__round__:实现内建函数round(),四舍五入。__ceil__:实现内建函数math.ceil(),大于原始值的最小整数。__floor__:实现内建函数math.floor(),小于原始值的最大整数__trunc__:实现内建函数math.trunc(),朝零取整__index__:作为列表索引的数字。
1 | |
二元操作符
比较运算符重载
__eq__(self, other)
__ne__(self, other)
__lt__(self, other)
__le__(self, other)
__gt__(self, other)
__ge__(self, other)
分别实现 ==、!=、 < 、 <= 、 > 、 >= 运算符。
算数运算符
__add__(self, other)
__sub__(self, other)
__mul__(self, other)
__truediv__(self, other)
__floordir__(self, other)
__mod__(self, other)
__pow__(self, other)
__and__(self, other)
__or__(self, other)
__xor__(self, other)
__lshift__(self, other)
__rshift__(self, other)
__matmul__(self, other)
分别表示+、-、*、/、//、%、**、&、|、^、<<、>>和@。
这玩意太多了,上面只是简单列举了最常见的。
反算数运算符
上面探讨的算数运算符要求位于运算符前面的对象实现,比如:
1 | |
这个式子中,要求 first 必须实现 __add__ 方法。
但是如果你没办法保证 first 的具体实现,那么也可以在 second 实现反算数运算符 __radd__,达到同样的效果。
反算数运算的名称就是在正常算数运算符前面加字母 r,比如 __radd__ 、 __rsub__,就不展开讲了。
增量赋值符
与反算数运算符类似的还有增量赋值符,比如最常用的 +=:
1 | |
其他的增量赋值符的还有 __isub__ 、 __imul__ 等,也不展开列举了。
表示相关
__str__(self)
__repr__(self)
__repr__goal is to be unambiguous__str__goal is to be readable- Container’s
__str__uses contained objects’__repr__
Implement __repr__ for any class you implement. This should be second nature. Implement __str__ if you think it would be useful to have a string version which errs on the side of readability.
__format__(self, spec_str)
这个方法可以扩展自己在使用format格式化的时候支持的功能集
__dir__(self) 定义了调用 dir() 时的行为,返回对象的属性、方法的列表
__dict__ 属性:对于实例,它存储实例属性;对于类,它存储类的属性和方法。
可调用
__call__(self, *args, **kwargs)