English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Основной учебник Python

Контроль потока в Python

Функции Python

Типы данных Python

Файловые операции в Python

Объекты и классы в Python

Даты и время в Python

Продвинутые знания Python

Руководство Python

Перегрузка операторов в Python

Вы можете изменить значение оператора в Python в зависимости от используемого операнда. Это называется перегрузкой операторов.

Что такое перегрузка операторов в Python?

Операторы PythonДля встроенных классов. Но тот же оператор может вести себя по-разному для различных типов. Например, оператор + выполняет арифметическую сумму двух чисел, объединяет два списка и соединяет два строки.

Эта функция в Python позволяет одному и тому же оператору иметь разное значение в зависимости от контекста, что называется перегрузкой операторов.

Что произойдет, когда мы будем использовать их с объектами пользовательских классов? Давайте посмотрим на следующий класс, который пытается имитировать точку в двумерной координатной системе.

class Point:
    def __init__(self, x = 0, y = 0):
        self.x = x
        self.y = y

Теперь запустите код и попробуйте добавить два точки в Python shell.

>>> p1 = Point(2,3)
>>> p2 = Point(-1,2)
>>> p1 + p2
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'

О, это много ошибок! Ошибка TypeError возникает, потому что Python не знает, как добавить два объекта Point.

Но хорошая новость в том, что мы можем научить Python этому через перегрузку операторов. Но сначала давайте разберемся с специальными функциями.

Специальные функции в Python

Функции класса, начинающиеся с двойного подчеркивания __, в Python называются特殊ными функциями. Потому что они не обычные функции. Функция __init__() которую мы определили выше, является одной из них. Она вызывается каждый раз, когда мы создаем новый объект класса. В Python много специальных функций.

Используя специальные функции, мы можем сделать наш класс совместимым с вграденными функциями.

>>> p1 = Point(2,3)
>>> print(p1)
<__main__.Point object at 0x00000000031F8CC0>

Вывод не достиг ожидаемого результата. Но если мы определим метод __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().

>>> p1 = Point(2,3)
>>> print(p1)
(2,3)

 Доказано, что это лучше, когда мы используем встроенную функцию str() или format(), которая вызовет один и тот же метод format().

>>> str(p1)
'(2,3)'
>>> format(p1)
'(2,3)'

因此,当您执行str(p1)或format(p1)时,Python在内部执行p1.__str__()。因此得名,特殊函数。下面继续回到操作符重载。

在Python中重载+运算符

要重载+符号,我们将需要在类中实现__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)

现在,让我们再试一次。

>>> p1 = Point(2,3)
>>> p2 = Point(-1,2)
>>> print(p1 + p2)
(1,5)

实际上发生的是,当您执行p1 + p2时,Python会调用p1 .__ add __(p2),也就是Point .__ add __(p1,p2)。 同样,我们也可以重载其他运算符。 我们需要实现的特殊函数列表如下。

Python中运算符重载的特殊函数
运算符表达在内部
相加(+)p1 + p2p1 .__ add __(p2)
相减(-)p1-p2p1 .__ sub __(p2)
相乘(*)p1 * p2p1 .__ mul __(p2)
求幂(**)p1 ** p2p1 .__ pow __(p2)
相除(/)p1 / p2p1 .__ truediv __(p2)
整除(//)
p1 // p2p1 .__ floordiv __(p2)
求模 (%)p1%p2p1 .__ mod __(p2)
按位左移(<<)p1 << p2p1 .__ lshift __(p2)
按位右移(>>)p1 >> p2p1 .__ rshift __(p2)
按位与(and)p1 and p2p1 .__ and __(p2)
按位或(or)p1 | 2p1 .__ or __(p2)
按位异或(^)p1 ^ p2p1 .__ xor __(p2)
按位否(~)〜p1p1 .__ invert __()

Перегрузка сравнительных операторов в Python

Python не ограничивает перегрузку операторов только арифметическими операторами. Мы также можем перегрузить сравнительные операторы.

Предположим, что мы хотим реализовать оператор "меньше" (<) в классе 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 __lt__(self, other):
        self_mag = (self.x ** 2) + (self.y ** 2)
        other_mag = (other.x ** 2) + (other.y ** 2)
        return self_mag < other_mag

Попробуйте запустить эти примеры в интерпретаторе Python.

>>> Point(1,1) < Point(-2,-3)
True
>>> Point(1,1) < Point(0.5,-0.2)
False
>>> Point(1,1) < Point(1,1)
False

Аналогично, ниже перечислены особые функции, которые нам нужно реализовать для перегрузки других сравнительных операторов.

Перегрузка сравнительных операторов в Python
Оператор
ВыражениеВнутренний
Меньше (<)p1 < p2p1 .__ lt __ (p2)
Меньше или равно (<=)p1 <= p2p1 .__ le __ (p2)

Равно (==)

p1 == p2p1 .__ eq __ (p2)
Не равно (!=)p1 != p2p1 .__ ne __ (p2)
Больше (>)p1 > p2p1 .__ gt __ (p2)
Больше или равно (>=)p1 >= p2p1 .__ ge __ (p2)