Python 运算符重载
Python 运算符重载
您可以根据使用的操作数更改 Python 中运算符的含义。在本教程中,您将学习如何在 Python 面向对象编程中使用运算符重载。
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)
输出
Traceback (most recent call last): File "<string>", line 9, in <module> print(p1+p2) TypeError: unsupported operand type(s) for +: 'Point' and 'Point'
在这里,我们可以看到一个 TypeError
提出了,因为 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()
时会调用相同的方法 或 format()
.
>>> str(p1)
'(2,3)'
>>> format(p1)
'(2,3)'
所以,当你使用 str(p1)
或 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<p2)
print(p2<p3)
print(p1<p3)
输出
True False False
同样,我们需要实现的特殊功能,以重载其他比较运算符如下表。
运算符 | 表达式 | 内部 |
---|---|---|
小于 | 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) |
Python