Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Python

Перегрузка операторов в Python: практическое руководство

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

Узнайте, как переопределять поведение операторов в Python с помощью специальных методов вроде __add__, __lt__ и других, улучшая ваши ООП-дизайны.

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

Встроенные операторы Python работают по-разному в зависимости от типов операндов. Оператор +, например, складывает числа, конкатенирует строки или объединяет списки. Эта гибкость достигается через перегрузку операторов — возможность присваивать контекстно-зависимые значения операторам для ваших собственных классов.

Рассмотрим простой класс Point, представляющий координату в 2D-плоскости. Без специальных методов попытка сложить две точки вызовет TypeError:

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'

Поскольку Python не знает, как комбинировать два экземпляра Point, он выбрасывает исключение. Перегрузка операторов позволяет нам определить это поведение самим.


Специальные методы Python

Методы, окружённые двойными подчёркиваниями — __init__, __str__, __add__ и т.д. — называются специальными методами или «dunder»-методами. Они вызываются неявно средой выполнения Python и являются точками перехвата для перегрузки операторов, протоколов контейнеров и многого другого.

Например, метод __str__ управляет тем, как объект преобразуется в человекочитаемую строку. По умолчанию печать объекта показывает его адрес в памяти, что часто бесполезно. Переопределение __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)

Теперь при печати Point мы получаем:

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

Вывод

(2, 3)

То же представление используется str(p1) и format(p1), так как Python внутренне вызывает p1.__str__().


Перегрузка оператора +

Чтобы настроить сложение для объектов Point, реализуйте __add__:

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):
        return Point(self.x + other.x, self.y + other.y)

Проверка нового поведения:

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

Вывод

(3, 5)

Под капотом Python выполняет p1.__add__(p2), возвращая новый Point со сложенными координатами.

Ниже — краткий справочник для других арифметических операторов и соответствующих специальных методов:

ОператорВыражениеСпециальный метод
Сложениеp1 + p2__add__(self, other)
Вычитаниеp1 - p2__sub__(self, other)
Умножениеp1 * p2__mul__(self, other)
Возведение в степеньp1 ** p2__pow__(self, other)
Делениеp1 / p2__truediv__(self, other)
Целочисленное делениеp1 // p2__floordiv__(self, other)
Остаток от деленияp1 % p2__mod__(self, other)
Левый сдвигp1 << p2__lshift__(self, other)
Правый сдвигp1 >> p2__rshift__(self, other)
Побитовое Иp1 & p2__and__(self, other)
Побитовое ИЛИp1 | p2__or__(self, other)
Побитовое XORp1 ^ p2__xor__(self, other)
Побитовое НЕ~p1__invert__(self)

Перегрузка операторов сравнения

Перегрузка операторов не ограничивается арифметикой. Операторы сравнения также можно адаптировать. Например, для сравнения точек по расстоянию от начала координат переопределите __lt__:

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)
print(p1 < p2)  # True
print(p2 < p3)  # False
print(p1 < p3)  # False

Остальные методы сравнения следуют схожему шаблону:

ОператорВыражениеСпециальный метод
Меньшеp1 < p2__lt__(self, other)
Меньше или равноp1 <= p2__le__(self, other)
Равноp1 == p2__eq__(self, other)
Не равноp1 != p2__ne__(self, other)
Большеp1 > p2__gt__(self, other)
Больше или равноp1 >= p2__ge__(self, other)

Тщательно определяя эти методы, вы можете заставить пользовательские объекты естественно участвовать в арифметических и сравнительных контекстах, тем самым повышая читаемость и поддерживаемость кода.

Python

  1. Освоение типов данных в Python: практическое руководство
  2. Мастерство операторов Python: Полное руководство
  3. Оператор pass в Python: практическое руководство
  4. Аргументы функций в Python: позиционные, именованные и параметры по умолчанию
  5. Словари в Python: создание, манипуляции и продвинутые техники
  6. Наследование в Python: концепции, синтаксис и практические примеры
  7. Итераторы в Python: как они работают и как создать свои
  8. Замыкания в Python: как вложенные функции захватывают переменные
  9. Декоратор @property в Python: чистые, обратно совместимые геттеры и сеттеры
  10. Модуль datetime в Python: практическое руководство по датам, времени и часовым поясам