【Python】笔记:正确重载运算符
正确重载运算符
一元运算符
-
(__neg__
)
+
(__pos__
) 最好返回 self 的副本
~
(__invert__
) 对整数位按位取反 (~x == -(x+1))
print(~2)
-3
中辍运算符
+
from array import array
from itertools import zip_longest
class Vector:
typecode = 'd'
def __init__(self, components) -> None:
self._componeents = array(self.typecode, components)
def __iter__(self):
return iter(self._componeents)
def __neg__(self):
return Vector(-x for x in self)
def __pos__(self):
return Vector(self)
def __add__(self, other):
pairs = zip_longest(self, other, fillvalue=0.0)
return Vector(a + b for a, b in pairs)
def __radd__(self, other):
return self + other # 直接委托给 __add__
Counter
collections.Count 计数器
from collections import Counter
ct = Counter('asfsdgasdasfasdgsd')
print(1, ct)
ct['s'] = -2
ct['g'] = 0
print(2, ct)
print(3, +ct) # 会剔除无意义的 0 和负值
1 Counter({'s': 6, 'a': 4, 'd': 4, 'f': 2, 'g': 2})
2 Counter({'a': 4, 'd': 4, 'f': 2, 'g': 0, 's': -2})
3 Counter({'a': 4, 'd': 4, 'f': 2})
def __add__(self, other):
try:
pairs = zip_longest(self, other, fillvalue=0.0)
return Vector(a + b for a, b in pairs)
except TypeError:
return NotImplemented
def __radd__(self, other):
return self + other
-
from array import array
from itertools import zip_longest
import reprlib, numbers
class Vector:
typecode = 'd'
def __init__(self, components) -> None:
self._componeents = array(self.typecode, components)
def __repr__(self):
components = reprlib.repr(self._componeents) # array('d', [1, 2, 3, 4, ...])
components = components[components.find('['):-1] # [1, 2, 3, 4, ...]
return 'Vector({})'.format(components) # Vector([1, 2, 3, 4])
def __iter__(self):
return iter(self._componeents)
def __mul__(self, scalar):
if isinstance(scalar, numbers.Real):
return Vector(n * scalar for n in self)
else:
return NotImplemented
def __rmul__(self, scalar):
return self * scalar
v1 = Vector([1, 2, 3])
print(1, repr(v1 * 10))
print(2, repr(20 * v1))
1 Vector([10.0, 20.0, 30.0])
2 Vector([20.0, 40.0, 60.0])
运算符 | 正向方法 | 逆向方法 | 就地方法 | 说明 |
---|---|---|---|---|
+ |
__add__ |
__radd__ |
__iadd__ |
加法或拼接 |
- |
__sub__ |
__rsub__ |
__isub__ |
减法 |
* |
__mul__ |
__rmul__ |
__imul__ |
乘法或重复复制 |
/ |
__truediv__ |
__rtruediv__ |
__itruediv__ |
除法 |
更多的
运算符 | 方法名字 |
---|---|
// |
floordiv |
% |
mod |
divmod() |
divmod |
** , pow() |
pow |
@ |
matmul |
& |
and |
` | ` |
^ |
xor |
<< |
lshift |
>> |
rshift |
pow(a, b, modulo)
<==> a ** b % modulo
@
是 点积,可在 numpy 中使用,a @ b
<==> dot(a, b)
from array import array
from itertools import zip_longest
import reprlib, numbers
class Vector:
typecode = 'd'
def __init__(self, components) -> None:
self._componeents = array(self.typecode, components)
def __repr__(self):
components = reprlib.repr(self._componeents) # array('d', [1, 2, 3, 4, ...])
components = components[components.find('['):-1] # [1, 2, 3, 4, ...]
return 'Vector({})'.format(components) # Vector([1, 2, 3, 4])
def __iter__(self):
return iter(self._componeents)
def __matmul__(self, other):
try:
return sum(a * b for a, b in zip(self, other))
except TypeError:
return NotImplemented
def __rmatmul__(self, other):
return self @ other
比较运算符
中辍运算符 | 正向方法调用 | 后备机制 |
---|---|---|
a == b |
a.__eq__(b) |
返回 id(a) == id(b) |
a != b |
a.__ne__(b) |
返回 not (a == b) |
a > b |
a.__gt__(b) |
抛出 TypeError |
a < b |
a.__lt__(b) |
抛出 TypeError |
a >= b |
a.__ge__(b) |
抛出 TypeError |
a <= b |
a.__le__(b) |
抛出 TypeError |
反向方法调用 b.__xx__(a)
from array import array
from itertools import zip_longest
import reprlib, numbers
class Vector:
typecode = 'd'
def __init__(self, components) -> None:
self._componeents = array(self.typecode, components)
def __repr__(self):
components = reprlib.repr(self._componeents) # array('d', [1, 2, 3, 4, ...])
components = components[components.find('['):-1] # [1, 2, 3, 4, ...]
return 'Vector({})'.format(components) # Vector([1, 2, 3, 4])
def __iter__(self):
return iter(self._componeents)
def __eq__(self, other):
if isinstance(other, Vector):
return (len(self) == len(other) and all(a == b for a, b in zip(self, other)))
else:
return NotImplemented
注意:
-
==
会调用a.__eq__(b)
进行判断 -
当
a.__eq__(b)
抛出NotImplemented
异常时, -
会调用反向方法
b.__eq__(a)
进行判断, -
如果再次得到
NotImplemented
, 则返回False
-
否则返回
True
在两个自定义 class 时判断是否相等时, 可能第一个 class 抛出 NotImplemented
, 而第二个 class 通过, 同样返回 True
!=
类似于 not ==
增量赋值运算符
后面忘保存了。。。
本文来自博客园,作者:Zinc233,转载请注明原文链接:https://www.cnblogs.com/Zinc233/p/FluentPython_S13.html