在 Python 内置类型中为许多操作符提供了自然语义支持。例如,a + b 这样的表达式对于数字类型来说就是加法操作,而对于序列对象来说就是串联操作。
那么当我们定义自己的类的时候,我们想要获得这样的操作支持时,那就需要在类中部署具体的方法,从而获得了操作符协议的支持。最后自定义类的实例也具备了相应的操作符支持。
默认情况,不对自定义类做加号+操作符协议的定义。如果你在写一个类,要想让自己的类获得某种操作支持,那么就要使用操作符加载技术来实现。也就是说,在类里部署一个具体的方法。例如,加号+操作符协议要部署 dunder add 方法,部署这个方法后,会让右边的被操作数 b 作为参数,然后返回 a + b 表达式的结果。
也就是说,a + b 表达式会变成一种调用方法的形式,那么 a + b == a.__add__(b)
同类的这些操作协议名有许多,每一个操作符都会对应一个操作协议方法名。如果在自定义类中没有部署这样的操作符协议方法的话,那么不支持操作符这样的操作。
操作符协议映射关系如下:
'a + b':('a.__add__(b)','b.__radd__(a)'),
'a - b':('a.__sub__(b)','b.__rsub__(a)'),
'a * b':('a.__mul__(b)','b.__rmul__(a)'),
'a / b':('a.__truediv__(b)','b.__rtruediv__(a)'),
'a // b':('a.__floordiv__(b)','b.__rfloordiv__(a)'),
'a % b':('a.__mod__(b)','b.__rmod__(a)'),
'a ** b':('a.__pow__(b)','b.__rpow__(a)'),
'a << b':('a.__lshift__(b)','b.__rlshift__(a)'),
'a >> b':('a.__rshift__(b)','b.__rrshift__(a)'),
'a & b':('a.__and__(b)','b.__rand__(a)'),
'a ^ b':('a.__xor__(b)','b.__rxor__(a)'),
'a | b':('a.__or__(b)','b.__ror__(a)'),
'a += b':'a.__iadd__(b)',
'a -= b':'a.__isub__(b)',
'a *= b':'a.__imul__(b)',
'+a':'a.__pos__()',
'-a':'a.__neg__()',
'~a':'a.__invert__()',
'abs(a)':'a.__abs__()',
'a < b':'a.__lt__(b)',
'a <= b':'a.__le__(b)',
'a > b':'a.__gt__(b)',
'a >= b':'a.__ge__(b)',
'a == b':'a.__eq__(b)',
'a != b':'a.__ne__(b)',
'v in a':'a.__contains__(v)',
'a[k]':'a.__getitem__(k)',
'a[k]= v':'a.__setitem__(k,v)',
'del a[k]':'a.__delitem__(k)',
'f(argv1, argv2)':'a.__call__(argv1, argv2)',
'len(a)':'a.__len__()',
'hash(a)':'a.__hash__()',
'iter(a)':'a.__iter__()',
'next(a)':'a.__next__()',
'bool(a)':'a.__bool__()',
'float(a)':'a.__float__()',
'int(a)':'a.__int__()',
'repr(a)':'a.__repr__()',
'reversed(a)':'a.__reversed__()',
'str(a)':'a.__str__()',