【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 ==

增量赋值运算符

后面忘保存了。。。

posted @ 2022-12-03 21:13  Zinc233  阅读(13)  评论(0编辑  收藏  举报