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 лекция
Недоступна
Перегрузка операторов индексации
Перегрузка операторов индексации
Комментарии (12)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Vanil'ka Уровень 25
18 августа 2025
Вторая задача просто балдёж! Устал уже от ленивых задач!
Павел Уровень 25
18 августа 2025
На самом деле вторая задача очень понравилась, наконец это не односложная копирка, а на подумать и вспомнить! Матрицы последний раз делали уроке в третьем и пришлось вспомнить как ее создать, а обработка ошибок была темы 3-4 назад.
Егор Уровень 22
14 августа 2025
В целом понял, что хочет 2 задача. Долго думал, после возвращения как лучше сделать и сделал. Проводил запуск без проверки, все работает согласно условиям задачи. Запустил проверку, ни одно условие не выполнено. И так уже покрутил и тут подтянул. Затем уже не выдержал, открыл правильное решение и удивился... все написано точно то же самое, за исключением имен переменных. Удалил пару пустых строк, поставил пробелы между операторами, то есть просто "прихорошил" визуально код и все зачлось... По итогу 5 попыток, хотя работала уже самая первая. Не то чтобы меня прямо сильно волнует, со скольки попыток будет сделано, но в такие моменты задница подгорает не из-за своей тупости, а из-за каких то скрытых условий, чтобы решение прошло
Владимир Тепляков Уровень 20 Expert
6 июня 2025
Мда, последние модули характеризуются особой степенью идиотии: 1) где-то мы даем задачи, которые можно скопировать из примеров 2) а где-то даем задачи, которые вообще хрен пойми как решать)
22 марта 2025
Программа должна включать определение класса Matrix, который будет представлять собой двумерную матрицу. - не могу понять это условие, как это реализовать в ините?
Алексей Уровень 32
16 июля 2025
def __init__(self, a, b): self.a = a self.b = b self.arr = [[0 for i in range(self.a)] for j in range(self.b)]
Mr.Robot Уровень 21 Expert
20 марта 2025
CustomList в примере выше не настоящий список, потому, что в нем отсутствует метод итератора. Это нужно, к слову, держать в голове с предыдущей лекции либо хорошо знать и понимать. Обязательные для списков методы __getitem__ и __setitem__ позволяют обращаться к элементам списка по индексу. Если эти геттеры-сеттеры будут отсутствовать, то при попытке обратиться по индексу будет возвращаться исключение TypeError: ... object is not subscriptable. Как-то кусочно-выборочно теория идет, а задания подразумевают целостный охват темы. Без ChatGPT ни решить ни разобраться, короче, если нет достаточного опыта разработки на питоне. (
Sergey O. Уровень 64
26 июня 2025
Не обязательно опыт или чат - просто банальный дебагинг через print (или f7). Опираемся на названия методов в условии (__getitem__ и __setitem__): находим их сигнатуру либо в теории (либо в автодополнении пайчарм). Добавляем методы в класс с print(index) в первой строке (или запускаем в режиме shift+f9 и прожимаем f7 до перехода в метод) и понимаем, что методы через параметр index получают кортежи с индексами. Остальное: создать/сохранить в поле список списков, изменить/вернуть значение по индексу кажется не трудно.
Mr.Robot Уровень 21 Expert
19 марта 2025
19.03.2025
UnknownReboot Уровень 30
27 февраля 2025
Как можно решить эти задачи? Уровень сложности запредельный. Или со мной что то не так (((
Екатерина Уровень 76
9 сентября 2024
Вторая задача про создание класса Matrix. В ините сразу бы создать матрицу нужного размера с нулями в качестве элементов и сохранить бы её размеры. В геттере и сеттере индексы принимаются одним аргументом типа tuple. В сеттере сначала принимаются индексы (tuple), затем значение. В геттере и сеттере проверяла выход индексов за пределы размерности матрицы и пробрасывала исключение IndexError, а в основной части кода ловила это исключение через try - except и выдавала соответствующее сообщение.
Anonymous #2923722 Уровень 21
11 февраля 2025
спасибо про tuple. сидел мучался, индексы по отдельности передавал)