📜  Python运算符重载

📅  最后修改于: 2020-09-19 14:07:19             🧑  作者: Mango

您可以根据所使用的操作数来更改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 "", line 9, in 
    print(p1+p2)
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'

在这里,我们可以看到TypeErrorTypeError ,因为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) 。此后,将按照我们指定的方式执行加法运算。

同样,我们也可以重载其他运算符。我们需要实现的特殊函数列表如下。

重载比较运算符

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

输出

True
False
False

同样,下面列出了我们需要实现以重载其他比较运算符的特殊功能。