目录
Python 2.2 之后,对类和类型进行了统一,int()、float()、str()、list()、tuple()等都由内置函数变为了工厂函数,也即类对象;
因此,在 Python 中的各种赋值操作,实际上是创建相应的实例对象,各种数值间的操作也就相当于调用实例对象的各种方法;
Python 内置了类对象的数值魔法方法,可以通过重构这些数值方法,自定义任何对象间的数值运算、操作。
- #通常内置函数(BIF)类型如下
- type(len)
- <class 'builtin_function_or_method'>
-
- #工厂函数类型如下,为类对象
- type(int)
- <class 'type'>
-
- #x、y的赋值实际上是创建类对象 int 的实例对象的过程
- x = int('1')
- y = int(1.1)
-
- #x、y的加法运算,即使用了类对象内置的数值方法
- x + y
- 2
Python 中二元运算,即正运算的数值方法中如下表:
魔法方法 | 含义 |
__add__(self, other) | 定义加法的行为:+ |
__sub__(self, other) | 定义减法的行为:- |
__mul__(self, other) | 定义乘法的行为:* |
__truediv__(self, other) | 定义真除法的行为:/ |
__floordiv__(self, other) | 定义整数除法的行为:// |
__mod__(self, other) | 定义取模算法的行为:% |
__divmod__(self, other) | 定义当被 divmod() 调用时的行为 |
__pow__(self, other[, modulo]) | 定义当被 power() 调用或 ** 运算时的行为 |
__lshift__(self, other) | 定义按位左移位的行为:<< |
__rshift__(self, other) | 定义按位右移位的行为:>> |
__and__(self, other) | 定义按位与操作的行为:& |
__xor__(self, other) | 定义按位异或操作的行为:^ |
__or__(self, other) | 定义按位或操作的行为:| |
正运算,即给出的参数从左至右参与运算符运算,如 __add__(self, other),即定义了 self + other 的数值运算;
需要注意的是,重构数值方式时,方法中不要直接调用正在重构的数值方法,可能会导致无限递归错误;
- #基于 int 创建一个新的类,重构加法运算
- class Newint(int):
- def __add__(self, other):
- addresult = self - other
- return addresult
-
- #新类的实例对象,使用加号,调用的重构后加法运算
- x = Newint(5)
- y = Newint('2')
- x + y
- 3
-
- #重构数值方法时,方法中调用了正在重构的数值方法
- class Newint2(int):
- def __add__(self, other):
- addresult = self - other
- return addresult
- def __sub__(self, other):
- subresult = self + other
- return subresult
-
- #新类的实例对象,调用加法触发无限递归
- x = Newint2(0)
- y = Newint2(1)
- x + y
- Traceback (most recent call last):
- File "<input>", line 1, in <module>
- File "<input>", line 3, in __add__
- File "<input>", line 6, in __sub__
- File "<input>", line 3, in __add__
- File "<input>", line 6, in __sub__
- ……
- File "<input>", line 3, in __add__
- File "<input>", line 6, in __sub__
- RecursionError: maximum recursion depth exceeded
-
- #重构数值方法时,如方法中需要调用被重构的数值方法
- #将数值运算所调用的参数,重新创建为非当前类(如下例子中使用父类 int)的实例对象
- class Newint2(int):
- def __add__(self, other):
- addresult = int(self) - int(other)
- return addresult
- def __sub__(self, other):
- subresult = int(self) + int(other)
- return subresult
-
- #新类的实例对象,调用重构的数值方法,运算正常
- x = Newint2(0)
- y = Newint2(1)
- x + y
- -1
- x - y
- 1
Python 中右侧二元运算,即反运算的数值方法中如下表:
魔法方法 | 含义 |
__radd__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rsub__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rmul__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rtruediv__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rfloordiv__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rmod__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rdivmod__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rpow__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rlshift__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rrshift__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rand__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__rxor__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
__ror__(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
这些方法是前一节中二元运算的右侧副本,有着相同的参数表和计算方法,但是从右侧开始调用参数;
反运算,给出的参数从右至左参与运算符运算,如 __radd__(self, other),即定义了 other + self 的数值运算;
反运算方法,只有当实例对象在运算符右侧,且运算符左侧不是执行该运算的类的一个实例对象时调用;
具体应该在何时使用正运算,何时使用反运算如下:
- #创建类,重构加法和反加法
- class Newint(int):
- def __add__(self, other):
- addresult = (int(self) + int(other)) * 10
- return addresult
- def __radd__(self, other):
- raddresult = (int(self) + int(other)) // 10
- return raddresult
-
- #instance + instance 运行 __add__
- x + y
- 130
-
- #instance + noninstance 运行 __add__
- x + 5
- 130
-
- #noninstance + instance 运行 __radd__
- 8 + y
- 1
Python 中增量二元运算的数值方法中如下表:
魔法方法 | 含义 |
__iadd__(self, other) | 定义赋值加法的行为:+= |
__isub__(self, other) | 定义赋值减法的行为:-= |
__imul__(self, other) | 定义赋值乘法的行为:*= |
__itruediv__(self, other) | 定义赋值真除法的行为:/= |
__ifloordiv__(self, other) | 定义赋值整数除法的行为://= |
__imod__(self, other) | 定义赋值取模算法的行为:%= |
__ipow__(self, other[, modulo]) | 定义赋值幂运算的行为:**= |
__ilshift__(self, other) | 定义赋值按位左移位的行为:<<= |
__irshift__(self, other) | 定义赋值按位右移位的行为:>>= |
__iand__(self, other) | 定义赋值按位与操作的行为:&= |
__ixor__(self, other) | 定义赋值按位异或操作的行为:^= |
__ior__(self, other) | 定义赋值按位或操作的行为:|= |
增量二元方法,要同时执行二元运算和赋值,需要在方法中执行操作(修改 self)和返回结果(可能是self);
此外,调用增量二元方法时,还需要考虑二元正运算和反运算。
魔法方法 | 含义 |
_pos__(self) | 定义正号的行为:+x |
__neg__(self) | 定义负号的行为:-x |
__abs__(self) | 定义当被 abs() 调用时的行为 |
__invert__(self) | 定义按位求反的行为:~x |
魔法方法 | 含义 |
__complex__(self) | 定义当被 complex() 调用时的行为(需要返回恰当的值) |
__int__(self) | 定义当被 int() 调用时的行为(需要返回恰当的值) |
__float__(self) | 定义当被 float() 调用时的行为(需要返回恰当的值) |
__round__(self[, n]) | 定义当被 round() 调用时的行为(需要返回恰当的值) |
__index__(self) | 1. 当对象是被应用在切片表达式中时,实现整形强制转换 |