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

Магические методы в Python — это специальные методы, которые начинаются и заканчиваются двумя символами подчеркивания (__). Они предоставляют дополнительные функциональные возможности и позволяют настраивать поведение объектов. Эти методы автоматически вызываются интерпретатором Python в определенных ситуациях.

Зачем нужны магические методы?

  • Они позволяют вам переопределять встроенные операции языка, такие как сложение (+), умножение (*) и другие.
  • Магические методы делают ваш код более читаемым и интуитивно понятным.
  • Они обеспечивают более глубокую интеграцию ваших классов с языком Python.

Некоторые популярные магические методы

МетодОписание
__init__Конструктор класса. Автоматически вызывается при создании объекта.
__str__Возвращает строковое представление объекта. Используется при преобразовании объекта в строку.
__add__Определяет операцию сложения для вашего класса. Вызывается при использовании оператора +.
__len__Возвращает длину объекта. Используется при вызове функции len().

Пример использования магических методов

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    
    def __str__(self):
        return f"Вектор({self.x}, {self.y})"

v1 = Vector(3, 4)
v2 = Vector(1, 2)
result = v1 + v2
print(result)  # Вектор(4, 6)

В этом примере магический метод __add__ позволяет складывать объекты класса Vector с использованием обычного оператора +. Метод __str__ предоставляет удобное строковое представление объекта.

Ниже приведён список основных магических методов и их описания:

1. Конструктор и деструктор

  • __new__(cls, ...): Создает новый экземпляр класса перед инициализацией. Обычно используется для изменения поведения конструктора.
  • __init__(self, ...): Инициализирует созданный экземпляр класса. Часто используется для установки начальных значений атрибутов.
  • __del__(self): Деструктор, вызывается при удалении экземпляра класса сборщиком мусора. Не всегда гарантируется вызов.

2. Представление объекта

  • __repr__(self): Возвращает строку, представляющую объект. Используется для отображения объекта в консоли или при отладке.
  • __str__(self): То же самое, что и __repr__, но обычно возвращает более человеко-понятную версию представления объекта.
  • __bytes__(self): Преобразует объект в байтовый тип.
  • __format__(self, format_spec): Позволяет настраивать формат вывода объекта с помощью спецификаторов формата.

3. Доступ к атрибутам

  • __getattr__(self, name): Вызывается, когда атрибут не найден обычным способом.
  • __getattribute__(self, name): Вызывается при каждом обращении к атрибуту объекта.
  • __setattr__(self, name, value): Вызывается при установке значения атрибута.
  • __delattr__(self, name): Вызывается при удалении атрибута.
  • __dir__(self): Возвращает список атрибутов объекта.

4. Контекстные менеджеры

  • __enter__(self): Вызывается при входе в блок with.
  • __exit__(self, exc_type, exc_val, exc_tb): Вызывается при выходе из блока with, независимо от наличия исключений.

5. Операции сравнения

  • __lt__(self, other): Меньше чем (<).
  • __le__(self, other): Меньше или равно (<=).
  • __eq__(self, other): Равно (==).
  • __ne__(self, other): Не равно (!=).
  • __gt__(self, other): Больше чем (>).
  • __ge__(self, other): Больше или равно (>=).

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

  • __add__(self, other): Сложение (+).
  • __sub__(self, other): Вычитание (-).
  • __mul__(self, other): Умножение (*).
  • __matmul__(self, other): Матричное умножение (@).
  • __truediv__(self, other): Деление (/).
  • __floordiv__(self, other): Целочисленное деление (//).
  • __mod__(self, other): Остаток от деления (%).
  • __divmod__(self, other): Функция divmod().
  • __pow__(self, other[, modulo]): Возведение в степень (**).
  • __lshift__(self, other): Битовый сдвиг влево (<<).
  • __rshift__(self, other): Битовый сдвиг вправо (>>).
  • __and__(self, other): Побитовое И (&).
  • __xor__(self, other): Побитовое исключающее ИЛИ (^).
  • __or__(self, other): Побитовое ИЛИ (|).

7. Отрицания арифметических операций

  • __neg__(self): Унарный минус (-x).
  • __pos__(self): Унарный плюс (+x).
  • __abs__(self): Абсолютная величина (abs(x)).
  • __invert__(self): Битовое отрицание (~x).

8. Приведение типов

  • __int__(self): Преобразование в целое число (int(x)).
  • __float__(self): Преобразование в вещественное число (float(x)).
  • __complex__(self): Преобразование в комплексное число (complex(x)).
  • __bool__(self): Преобразование в булево значение (bool(x)).
  • __index__(self): Преобразование в целочисленный индекс (bin(x), oct(x), hex(x)).

9. Протоколы итераций

  • __len__(self): Длина контейнера (len(x)).
  • __getitem__(self, key): Доступ по ключу (x[key]).
  • __setitem__(self, key, value): Присваивание по ключу (x[key] = value).
  • __delitem__(self, key): Удаление элемента по ключу (del x[key]).
  • __iter__(self): Возвращает итератор для объекта.
  • __next__(self): Следующий элемент итератора.
  • __contains__(self, item): Проверка на наличие элемента в объекте (item in x).
  • __reversed__(self): Обратная итерация.

10. Специальные случаи

  • __call__(self, ...): Позволяет объекту вести себя как функция (instance(...)).
  • __hash__(self): Хэш объекта (hash(x)).
  • __sizeof__(self): Размер объекта в байтах (sys.getsizeof(x)).
  • __slots__: Список имен атрибутов, которые будут доступны в классе.

Это далеко не полный список всех магических методов, существующих в Python, однако он включает большинство часто используемых методов.

Методы математических операций с буквами r и i в начале имени

Рассмотрим назначение некоторых специальных методов.

  • __radd__(self, other) — other + self;
  • __rsub__(self, other) — other - self;
  • __rmul__(self, other) — other * self;
  • __rmatmul__(self, other) — other @ self;
  • __rtruediv__(self, other) — other / self;
  • __rfloordiv__(self, other) — other // self;
  • __rmod__(self, other) — other % self;
  • __rdivmod__(self, other) — divmod(other, self);
  • __rpow__(self, other) — other ** self;
  • __rlshift__(self, other) — other << self;
  • __rrshift__(self, other) — other >> self;
  • __rand__(self, other) — other & self;
  • __rxor__(self, other) — other ^ self;
  • __ror__(self, other) — other | self;
  • __iadd__(self, other) — self += other;
  • __isub__(self, other) — self -= other;
  • __imul__(self, other) — self *= other;
  • __imatmul__(self, other) — self @= other;
  • __itruediv__(self, other) — self /= other;
  • __ifloordiv__(self, other) — self //= other;
  • __imod__(self, other) — self %= other;
  • __ipow__(self, other) — self **= other;
  • __ilshift__(self, other) — self <<= other;
  • __irshift__(self, other) — self >>= other;
  • __iand__(self, other) — self &= other;
  • __ixor__(self, other) — self ^= other;
  • __ior__(self, other) — self |= other.

Покажем отличие методов математических операций с буквами r и i в начале имени от методов без этих букв:

class A:

    def __init__(self):
        self.value = 11

    def __add__(self, other):
        return "Выполняется метод __add__!"

    def __radd__(self, other):
        return "Выполняется метод __radd__!"

    def __iadd__(self, other):
        self.value += other
        return self

    def __str__(self):
        return f"value: {self.value}."

        
a = A()
print(a + 1)
print(1 + a)
a += 1
print(a)

Вывод программы:

Выполняется метод __add__!
Выполняется метод __radd__!
value: 12.

Для операции a + 1 был использован метод __add__. Для операции 1 + a был использован метод __radd__. А для операции += использован __iadd__. Обратите внимание: при выполнении методов, начинающихся с буквы i, недостаточно только изменить атрибуты объекта, нужно ещё вернуть объект из метода, иначе в объект запишется None.

Источник: https://stepik.org/lesson/1584656/step/4?unit=1606014

Было ли это полезно?

0 / 0