本文主要涵盖Python对象中的魔术方法。魔术方法是类对象中的一种特殊方法,这些方法拥有固定的参数列表和特殊的调用时机。
魔术方法以双下划线__开头,以双下划线结尾。
Python中的运算符重载通过魔术方法实现,因此可以将魔术方法分为与运算符无关的特殊方法及与运算符有关的特殊方法
与运算符无关的魔术方法
涉及到字符串与字节序列的魔术方法:
| 方法名 | 参数列表 | 调用时机 | 返回值类型 | 备注 |
|---|
__repr__ | self | 当调用repr()函数时 | str | 返回值应为重建该对象的Python表达式(如果可能),或包含其他信息的字符串<...> |
__str__ | self | 当调用str()函数时 | str | 调用print()等其他函数时会隐式调用__str__(),当不存在__str__()时会自动调用__repr__() |
__format__ | self, format_spec | 当调用format()函数时 | str | object.__format__(x, '')等价于str(x) |
__bytes__ | self | 当调用bytes()函数时 | bytes | 返回值是对象的字节表示 |
涉及到数值类型转换的魔术方法:
| 方法名 | 参数列表 | 调用时机 | 返回值类型 | 备注 |
|---|
__bool__ | self | 调用bool()函数时 | bool | 当__bool__函数没有定义时,会隐式 调用__len__,如果__len__也没有 定义,则返回True |
__complex__ | self | 调用commplex()函数时 | complex | |
__int__ | self | 调用int()函数时 | int | |
__float__ | self | 调用float()函数时 | float | |
__hash__ | self | 调用hash() | 函数时 | hash()函数将__hash__()的返回值 截断到Py_ssize_t的范围内,64位系 统下Py_ssize_t为8字节;set等类 型的操作也会调用对象的__hash__函 数 |
__index__ | self | 调用operator.index()或Python需要整数值时 | int | 当__int__、__float__、
__complex__没有实现时,这些函数隐式地调用__index__ |
集合相关操作:
| 方法名 | 参数列表 | 调用时机 | 返回值类型 | 备注 |
|---|
__len__ | self | 调用len()函数时 | int | 返回值必须为非负整数,在CPython中返回值不能超过sys.maxsize中定义的值,否则len()等函数会抛出OverflowError等异常 |
__getitemm__ | self, key | 使用[]运算符时(右值) | | key可以为合法的数组下标,也可以是反向的下标,也可以是序列的切片,该函数应在key类型不对应时抛出TypeError,key超出范围时抛出IndexError或KeyError(对于映射类型) |
__setitem__ | self, key, value | 使用[]运算符时(左值) | None | key参数的取值及异常处理与__getitem__函数相同 |
__delitem__ | self, key | 使用del删除序列中的元素时 | None | 对于不可删除的序列或映射,无需实现该函数,其他同__getitem__ |
__contains__ | self, item | 使用in作为运算符时 | bool | 对于映射类型,__contains__接收的item参数对应映射的key部分而不是value部分。若没有定义该函数,Python首先通过__iter__进行查找,其次使用__getitem__进行查找 |
迭代器与枚举类型:
| 方法名 | 参数列表 | 调用时机 | 返回值类型 | 备注 |
|---|
__iter__ | self | 调用iter()函数或使用循环时 | | 返回值应为可迭代对象,对于可迭代对象,__iter__函数返回自身 |
__reversed__ | self | 调用reversed()函数时 | | 返回值应为可迭代对象,且是原序列的逆序 |
__next__ | self | 调用next()函数时 | | 返回可迭代对象中的下一个元素,当到达最后一个元素时抛出StopIteration |
函数调用:
| 方法名 | 参数列表 | 调用时机 | 返回值类型 | 备注 |
|---|
__call__ | self, *args, **kwargs | 当对象以函数的方式被调用时 | | 定义了__call__方法的对象属于typing.Callable类型 |
上下文管理(with)关键词:
| 方法名 | 参数列表 | 调用时机 | 返回值类型 | 备注 |
|---|
__enter__ | self | 使用with关键词声明上下文时 | Any | 返回值分配给as关键词指明的对象 |
__exit__ | self, exc_type, exc_value, traceback | 离开with块时 | Any | 若with块执行过程中没有出现异常,则exc_type, exc_value, traceback参数均为None,否则exit块可以对异常进行处理 |
对象管理:
| 方法名 | 参数列表 | 调用时机 | 返回值类型 | 备注 |
|---|
__new__ | cls[, ...] | 创建类实例时 | Any | __new__为静态方法且先于__init__执行,__new__的其余参数会传递给__init__。若__new__返回的类型与创建的类型不对应,则不会执行__init__ |
__init__ | self, ... | 初始化类实例时 | None | 若基类定义了__init__,则在子类的__init__中必须有super().__init()的显式调用 |
__del__ | self | 对象销毁时 | None | 当对象的引用计数减为0时,对象才可能被删除 |
属性管理:
| 方法名 | 参数列表 | 调用时机 | 返回值类型 | 备注 |
|---|
__getattribute__ | self, name | 使用self.name访问对象的属性时 | Any | 为避免无限递归,子类的__getattribute__方法的实现中必须包含父类的__getattribute__方法调用 |
__getattr__ | self, name | 使用self.name访问对象的不存在属性或__getattribute__函数抛出AttributeError异常 | Any | 当__getattribute__正常执行时__getattr__不会执行 |
__setattr__ | self, name, value | 使用self.name设置属性的值时 | None | 当试图通过__setattr__向对象设置属性值时必须通过类型的__setattr__方法进行设置 |
__delattr__ | self, name | 执行del self.name时 | None | 仅当del self.name语句有意义时,才需要实现该方法 |
__dir__ | self | 执行dir()函数时 | Sequence | dir()会自动进行排序处理 |
与运算符有关的魔术方法
一元运算符
| 描述 | 方法名 | 运算符 |
|---|
| 取负 | __neg__ | - |
| 取正 | __pos__ | + |
| 绝对值 | __abs__ | abs() |
比较运算符
| 描述 | 方法名 | 运算符 |
|---|
| 小于 | __lt__ | < |
| 小于等于 | __le__ | <= |
| 等于 | __eq__ | == |
| 不等于 | __ne__ | != |
| 大于 | __gt__ | > |
| 大于等于 | __ge__ | >= |
算术运算符
| 描述 | 方法名 | 运算符 |
|---|
| 相加 | __add__ | + |
| 相减 | __sub__ | - |
| 相乘 | __mul__ | * |
| 实数除 | __truediv__ | / |
| 整数除 | __floordiv__ | // |
| 取余 | __mod__ | % |
| 整数除+取余 | __divmod__ | divmod() |
| 乘方 | __pow__ | ** |
| 取整 | __round__ | round() |
反向算术运算符在方法名前面加r,如__radd__。增量赋值算术运算符在方法名前面加i,如__iadd__。
位运算符
| 描述 | 方法名 | 运算符 |
|---|
| 按位取反 | __invert__ | ~ |
| 左移 | __lshift__ | << |
| 右移 | __rshift__ | >> |
| 按位与 | __and__ | & |
| 按位或 | __or__ | | |
| 按位异或 | __xor__ | ^ |
反向算术运算符在方法名前面加r,增量赋值算术运算符在方法名前面加i。