Python 运算符重载

Python 运算符适用于内置类。但是同一个操作符对于不同的类型有不同的表现。例如,+运算符将对两个数字执行算术加法、合并两个列表或连接两个字符串。
Python 中允许相同运算符根据上下文具有不同含义的这种特性称为运算符重载。
那么当我们将它们与用户定义类的对象一起使用时会发生什么?让我们考虑下面的类,它试图模拟二维坐标系中的一个点。

class Point: def init(self, x=0, y=0): self.x = x self.y = y p1 = Point(1, 2) p2 = Point(2, 3) print(p1+p2)
输出
回溯(最近一次调用最后一次): 文件“”,第 9 行,在 中 打印(p1+p2) 类型错误:+ 不支持的操作数类型:“点”和“点”
在这里,我们可以看到 aTypeError被提升了,因为 Python 不知道如何将两个Point对象相加。
但是,我们可以通过运算符重载在 Python 中实现此任务。但首先,让我们了解一下特殊功能。


Python 特殊函数

以双下划线开头的类函数在 Python 中称为特殊函数。
这些函数不是我们为类定义的典型函数。
init()我们上面定义的函数就是其中之一。每次我们创建该类的新对象时都会调用它。
Python 中还有许多其他特殊函数。访问Python 特殊函数以了解有关它们的更多信息。
使用特殊函数,我们可以使我们的类与内置函数兼容。
>>> p1 = Point(2,3) >>> print(p1) <
main.Point object at 0x00000000031F8CC0>
假设我们希望print()函数打印Point对象的坐标而不是我们得到的坐标。我们可以
str()在我们的类中定义一个方法来控制对象的打印方式。让我们看看我们如何实现这一目标:
class Point: def
init(self, x = 0, y = 0): self.x = x self.y = y def str__(self): return “({0},{1})”.format(self.x,self.y)

现在让我们print()再次尝试该功能。

class Point: def init(self, x=0, y=0): self.x = x self.y = y def str(self): return “({0}, {1})”.format(self.x, self.y) p1 = Point(2, 3) print(p1)
输出
(2, 3)
这样更好。事实证明,当我们使用内置函数str()or时会调用相同的方法format()。
>>> str(p1) ‘(2,3)’ >>> format(p1) ‘(2,3)’
因此,当您使用str(p1)or 时format(p1),Python 会在内部调用该p1.str()方法。因此得名,特殊功能。
现在让我们回到运算符重载。


重载 + 运算符

要重载+运算符,我们需要add()在类中实现函数。拥有权利的同时也被赋予了重大的责任。我们可以在这个函数内做任何我们喜欢的事情。但是返回一个Point坐标和的对象更明智。
class Point: def init(self, x=0, y=0): self.x = x self.y = y def str(self): return “({0},{1})”.format(self.x, self.y) def add(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y)
现在让我们再次尝试加法操作:

class Point: def init(self, x=0, y=0): self.x = x self.y = y def str(self): return “({0},{1})”.format(self.x, self.y) def add(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y) p1 = Point(1, 2) p2 = Point(2, 3) print(p1+p2)
输出
(3,5)
实际发生的是,当你使用p1 + p2,Python会自动调用p1.add(p2)这又是Point.add(p1,p2)。在此之后,加法操作按照我们指定的方式进行。
同样,我们也可以重载其他运算符。我们需要实现的特殊功能如下表所示。

操作员 表达 内部
添加 p1 + p2 p1.add(p2)
减法 p1 - p2 p1.sub(p2)
乘法 p1 * p2 p1.mul(p2)
力量 p1 ** p2 p1.pow(p2)
分配 p1 / p2 p1.truediv(p2)
楼层划分 p1 // p2 p1.floordiv(p2)
余数(模) p1 % p2 p1.mod(p2)
按位左移 p1 << p2 p1.lshift(p2)
按位右移 p1 >> p2 p1.rshift(p2)
按位与 p1 & p2 p1.and(p2)
按位或 p1 | p2 p1.or(p2)
按位异或 p1 ^ p2 p1.xor(p2)
按位非 ~p1 p1.invert()

重载比较运算符

Python 并不仅仅将运算符重载限制为算术运算符。我们也可以重载比较运算符。
假设我们想<在我们的Point类中实现小于符号符号。
让我们从原点比较这些点的大小并为此目的返回结果。它可以实现如下。

overloading the less than operator class Point: def init(self, x=0, y=0): self.x = x self.y = y def str(self): return “({0},{1})”.format(self.x, self.y) def lt(self, other): self_mag = (self.x 2) + (self.y 2) other_mag = (other.x 2) + (other.y 2) return self_mag < other_mag p1 = Point(1,1) p2 = Point(-2,-3) p3 = Point(1,-1) # use less than print(p1输出
真的 错误的 错误的
类似地,下面列出了我们需要实现的用于重载其他比较运算符的特殊函数。

操作员 表达 内部
少于 p1 < p2 p1.lt(p2)
小于或等于 p1 <= p2 p1.le(p2)
等于 p1 == p2 p1.eq(p2)
不等于 p1 != p2 p1.ne(p2)
比…更棒 p1 > p2 p1.gt(p2)
大于或等于 p1 >= p2 p1.ge(p2)