JavaRush /Курсы /Модуль 1: Python Core /Перегрузка операторов

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

Модуль 1: Python Core
11 уровень , 5 лекция
Открыта

6.1 Магические методы

Перегрузка операторов в Python позволяет определять или изменять поведение встроенных операторов (например, +, -, *, /) для пользовательских классов. Это делается с помощью специальных методов, которые также называются магическими методами.

Например, в своем классе вы можете перегрузить операторы сравнения:

Оператор Метод без подчеркивания Сигнатура метода
== eq() __eq__(self, other)
!= ne() __ne__(self, other)
< lt() __lt__(self, other)
<= le() __le__(self, other)
> gt() __gt__(self, other)
>= ge() __ge__(self, other)

Допустим, вы написали свой класс и хотите, чтобы объекты вашего класса сравнивались именно так, как вам это нужно. Вам нужно просто реализовать в вашем классе метод «__eq__», и Python будет вызывать его каждый раз, когда в коде сравниваются объекты вашего класса.

Пример:


class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
        
# Использование
v1 = Vector(2, 3)
v2 = Vector(2, 3)
v3 = Vector(4, 5)
print(v1 == v2)  # Выведет: True
print(v1 == v3)  # Выведет: False

Каждый раз, когда вы сравниваете два ваших объекта, Python проверяет, а нет ли у них реализованной функции «__eq__». Если есть, то вызывает ее. А вот если ее нет, то уже просто будет сравнивать ссылки на объекты.

Фактически в примере выше написано (только еще проверку на наличие метода нужно добавить):


# Использование
v1 = Vector(2, 3)
v2 = Vector(2, 3)
v3 = Vector(4, 5)
print(v1.__eq__(v2))  # Выведет: True
print(v1.__eq__(v3))  # Выведет: False

6.2 Список всех операторов

Всего для перегрузки доступно 6 групп операторов.

Арифметические операторы:

Оператор Метод без подчеркивания Сигнатура метода
+ add __add__(self, other)
- sub __sub__(self, other)
* mul __mul__(self, other)
/ truediv __truediv__(self, other)
// floordiv __floordiv__(self, other)
% mod __mod__(self, other)
** pow __pow__(self, other)

Операторы сравнения:

Оператор Метод без подчеркивания Сигнатура метода
== eq __eq__(self, other)
!= ne __ne__(self, other)
< lt __lt__(self, other)
<= le __le__(self, other)
> gt __gt__(self, other)
>= ge __ge__(self, other)

Логические операторы:

Оператор Метод без подчеркивания Сигнатура метода
& and __and__(self, other)
| or __or__(self, other)
^ xor __xor__(self, other)
~ invert __invert__(self)

Операторы индексации и срезов:

Оператор Метод
obj[key] __getitem__(self, key)
obj[key] = value __setitem__(self, key, value)
del obj[key] __delitem__(self, key)

Унарные операторы:

Оператор Метод
- __neg__(self)
+ __pos__(self)
abs() __abs__(self)
~ __invert__(self)

Операторы присваивания:

Оператор Метод
+= __iadd__(self, other)
-= __isub__(self, other)
*= __imul__(self, other)
/= __itruediv__(self, other)
//= __ifloordiv__(self, other)
%= __imod__(self, other)
**= __ipow__(self, other)

Возможно, поэтому Python такой медленный – каждый раз перед выполнением оператора он ищет аналогичную функцию у класса и всех его классов-родителей. Зато это позволяет писать самый компактный код в мире :)

6.3 Оператор индексации

То, что можно сравнивать объекты или вычитать множества – это в каком-то смысле очевидно. И вы сами догадаетесь об этом, если будете писать класс, который подразумевает над ним логические или математические операции.

Хочу с вами разобрать такой интересный пример – как оператор индексации. Давайте сразу начнем с кода примера:


class CustomList:
    def __init__(self, data):
        self.data = data
        
    def __getitem__(self, index):
        return self.data[index]
        
    def __setitem__(self, index, value):
        self.data[index] = value
        
    def __delitem__(self, index):
        del self.data[index]
        
    def __repr__(self):
        return repr(self.data)
        
# Использование
c_list = CustomList([1, 2, 3, 4, 5])
print(c_list[1])  # Выведет: 2
c_list[1] = 10
print(c_list)  # Выведет: [1, 10, 3, 4, 5]
del c_list[1]
print(c_list)  # Выведет: [1, 3, 4, 5]

Тут мы видим пример трех операций:

  • Чтение данных через индекс.
  • Запись данных через индекс.
  • И даже удаление данных через индекс.

А ведь совсем не обязательно, что данные внутри будут храниться в виде списка. Или индекс не обязательно должен быть числом. Например, класс dictionary (словарь) именно так и реализован.

Создаем SuperList

Помните класс list? Ему можно присваивать элементы, но только с теми индексами, которые уже есть. Давайте сделаем свой класс, назовем его SuperList, к элементам которого можно будет обращаться по любому индексу:

  • Если индекс < 0, то будем вставлять элемент в начало.
  • Если индекс >= len, то будем добавлять элемент в конец.
  • В остальных случаях просто возвращать элемент.

Пример:


class SuperList(list):
    def __init__(self, value):
        super().__init__(value)
        
    def __setitem__(self, index, value):
        if index >= len(self):
            super().append(value)
        elif index < 0:
            super().insert(0, value)
        else:
            super().__setitem__(index, value)
        
lst = SuperList([1, 2, 3])
lst[200] = 100
lst[-200] = 99
print(lst)  # [99, 1, 2, 3, 100]

Так что перегрузка индексов — отличная возможность, и я рекомендую пользоваться ею на практике. А на сегодня — все.

2
Задача
Модуль 1: Python Core, 11 уровень, 5 лекция
Недоступна
Перегрузка операторов сравнения
Перегрузка операторов сравнения
2
Задача
Модуль 1: Python Core, 11 уровень, 5 лекция
Недоступна
Перегрузка операторов индексации
Перегрузка операторов индексации
Комментарии (7)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Владимир Тепляков Уровень 20 Expert
6 июня 2025
Мда, последние модули характеризуются особой степенью идиотии: 1) где-то мы даем задачи, которые можно скопировать из примеров 2) а где-то даем задачи, которые вообще хрен пойми как решать)
22 марта 2025
Программа должна включать определение класса Matrix, который будет представлять собой двумерную матрицу. - не могу понять это условие, как это реализовать в ините?
Mr.Robot Уровень 21 Expert
20 марта 2025
CustomList в примере выше не настоящий список, потому, что в нем отсутствует метод итератора. Это нужно, к слову, держать в голове с предыдущей лекции либо хорошо знать и понимать. Обязательные для списков методы __getitem__ и __setitem__ позволяют обращаться к элементам списка по индексу. Если эти геттеры-сеттеры будут отсутствовать, то при попытке обратиться по индексу будет возвращаться исключение TypeError: ... object is not subscriptable. Как-то кусочно-выборочно теория идет, а задания подразумевают целостный охват темы. Без ChatGPT ни решить ни разобраться, короче, если нет достаточного опыта разработки на питоне. (
Mr.Robot Уровень 21 Expert
19 марта 2025
19.03.2025
UnknownReboot Уровень 26
27 февраля 2025
Как можно решить эти задачи? Уровень сложности запредельный. Или со мной что то не так (((
Екатерина Уровень 69
9 сентября 2024
Вторая задача про создание класса Matrix. В ините сразу бы создать матрицу нужного размера с нулями в качестве элементов и сохранить бы её размеры. В геттере и сеттере индексы принимаются одним аргументом типа tuple. В сеттере сначала принимаются индексы (tuple), затем значение. В геттере и сеттере проверяла выход индексов за пределы размерности матрицы и пробрасывала исключение IndexError, а в основной части кода ловила это исключение через try - except и выдавала соответствующее сообщение.
Anonymous #2923722 Уровень 21
11 февраля 2025
спасибо про tuple. сидел мучался, индексы по отдельности передавал)