Перегрузка оператора 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 (последний вызов последним): файл "", строка 9, в печати (p1 + p2) TypeError: неподдерживаемые типы операндов для +: 'Point' и 'Point'

Здесь мы видим, что TypeErrorбыл поднят a , поскольку Python не знал, как складывать два Pointобъекта вместе.

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

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

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

Эти функции не являются типичными функциями, которые мы определяем для класса. __init__()Функция мы определили выше , является одним из них. Он вызывается каждый раз, когда мы создаем новый объект этого класса.

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

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

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

Предположим, мы хотим, чтобы 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классе символ «меньше символа ».

Let us compare the magnitude of these points from the origin and return the result for this purpose. It can be implemented as follows.

 # 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 

Output

 True False False

Similarly, the special functions that we need to implement, to overload other comparison operators are tabulated below.

Operator Expression Internally
Less than p1 < p2 p1.__lt__(p2)
Less than or equal to p1 <= p2 p1.__le__(p2)
Equal to p1 == p2 p1.__eq__(p2)
Not equal to p1 != p2 p1.__ne__(p2)
Greater than p1> p2 p1.__gt__(p2)
Greater than or equal to p1>= p2 p1.__ge__(p2)

Интересные статьи...