Введение

Примеры

Методы магии / Дандер

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

Рассмотрим эту реализацию двумерных векторов.

 import math

class Vector(object):
    # instantiation
    def __init__(self, x, y):
        self.x = x
        self.y = y

    # unary negation (-v)
    def __neg__(self):
        return Vector(-self.x, -self.y)

    # addition (v + u)
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    # subtraction (v - u)
    def __sub__(self, other):
        return self + (-other)

    # equality (v == u)
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    # abs(v)
    def __abs__(self):
        return math.hypot(self.x, self.y)

    # str(v)
    def __str__(self):
        return '<{0.x}, {0.y}>'.format(self)

    # repr(v)
    def __repr__(self):
        return 'Vector({0.x}, {0.y})'.format(self)

 

Теперь можно , естественно , использовать экземпляры Vector класса в различных выражениях.

 v = Vector(1, 4)
u = Vector(2, 0)

u + v           # Vector(3, 4)
print(u + v)    # "<3, 4>" (implicit string conversion)
u - v           # Vector(1, -4)
u == v          # False
u + v == v + u  # True
abs(u + v)      # 5.0 

Тип контейнера и последовательности


Вызываемые типы


Обработка невыполненного поведения

Если ваш класс не реализует конкретный перегруженный оператор для типов аргументов , предоставленных, он должен return NotImplemented (обратите внимание , что это специальная константа , не то же самое , как NotImplementedError ). Это позволит Python попробовать другие методы, чтобы заставить работу работать:

Когда NotImplemented возвращается, интерпретатор будет пытаться отраженную операцию на другой тип или какой - либо другой запасной вариант, в зависимости от оператора. Если все попытки операции возвращают NotImplemented , интерпретатор выдаст соответствующее исключение.

Например, если x + y , если x.__add__(y) возвращает невыполненным, y.__radd__(x) попытка вместо этого.

 class NotAddable(object):

    def __init__(self, value):
        self.value = value

    def __add__(self, other):
        return NotImplemented


class Addable(NotAddable):

    def __add__(self, other):
        return Addable(self.value + other.value)

    __radd__ = __add__

 

Как это отражается метод , который мы должны реализовать __add__ и __radd__ получить ожидаемое поведение во всех случаях; к счастью, так как они оба делают одно и то же в этом простом примере, мы можем воспользоваться ярлыком.

В использовании:

 >>> x = NotAddable(1)
>>> y = Addable(2)
>>> x + x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'NotAddable' and 'NotAddable'
>>> y + y
<so.Addable object at 0x1095974d0>
>>> z = x + y
>>> z
<so.Addable object at 0x109597510>
>>> z.value
3

 

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

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

NB Использование other в качестве имени переменной не является обязательным, но считается нормой.

оператор  метод  выражение  + Сложение  __add__(self, other)   a1 + a2   - Вычитание  __sub__(self, other)   a1 - a2   * Умножение  __mul__(self, other)   a1 * a2   @ Умножение матриц  __matmul__(self, other)   a1 @ a2 (Python 3.5)  / Отдел  __div__(self, other)   a1 / a2 (только Python 2)  / Отдел  __truediv__(self, other)   a1 / a2 (Python 3)  // Отдел пола  __floordiv__(self, other)   a1 // a2   % Модульный / Остаток  __mod__(self, other)   a1 % a2   ** Мощность  __pow__(self, other[, modulo])   a1 ** a2   << побитового сдвига влево  __lshift__(self, other)   a1 << a2   >> побитовое смещение вправо   __rshift__(self, other)   a1 >> a2   & Побитовое  __and__(self, other)   a1 & a2   ^ Побитовое исключающее ИЛИ  __xor__(self, other)   a1 ^ a2   | (Побитовое ИЛИ)  __or__(self, other)   a1 | a2   - Отрицание (Арифметический)  __neg__(self)   -a1   + Положительно  __pos__(self)   +a1   ~ Побитовое НЕ  __invert__(self)   ~a1   < Меньше чем  __lt__(self, other)   a1 < a2    <= Меньше или равно  __le__(self, other)   a1 <= a2   == Равно  __eq__(self, other)   a1 == a2   != Не равно  __ne__(self, other)   a1 != a2   > Больше чем  __gt__(self, other)   a1 > a2   >= Больше или равно  __ge__(self, other)   a1 >= a2   [index] Оператор Индекс  __getitem__(self, index)   a1[index]   in операторах В  __contains__(self, other)   a2 in a1    (*args, ...) Вызов  __call__(self, *args, **kwargs)   a1(*args, **kwargs)

Необязательный параметр по modulo для __pow__ используется только в pow встроенной функции.

Каждый из методов , соответствующих бинарный оператор имеет соответствующий «правильный» метод , который начать с __r , например __radd__ :

 class A:
    def __init__(self, a):
        self.a = a
    def __add__(self, other):
        return self.a + other
    def __radd__(self, other):
        print("radd")
        return other + self.a

A(1) + 2  # Out:  3
2 + A(1)  # prints radd. Out: 3

 

а также соответствующая версия Inplace, начиная с __i :

 class B:
    def __init__(self, b):
        self.b = b
    def __iadd__(self, other):
        self.b += other
        print("iadd")
        return self

b = B(2)
b.b       # Out: 2
b += 1    # prints iadd
b.b       # Out: 3

 

Поскольку в этих методах нет ничего особенного, многие другие части языка, части стандартной библиотеки и даже сторонние модули самостоятельно добавляют магические методы, такие как методы для приведения объекта к типу или проверки свойств объекта. Например, встроенная str() вызов функции объекта __str__ метод, если он существует. Некоторые из этих видов использования перечислены ниже.

функция  метод  выражение  Кастинг для int  __int__(self)   int(a1)   Абсолютная функция  __abs__(self)   abs(a1)   Кастинг на str   __str__(self)   str(a1)   Кастинг для unicode  __unicode__(self)   unicode(a1) (Python 2 только)  Строковое представление  __repr__(self)   repr(a1)   Приведение к bool  __nonzero__(self)   bool(a1)   Форматирование строки  __format__(self, formatstr)   "Hi {:abc}".format(a1)   хеширования  __hash__(self)   hash(a1)   длина  __len__(self)   len(a1)   округление  __round__(self)   round(a1)   Перевернутый  __reversed__(self)   reversed(a1)   Этаж   __floor__(self)   math.floor(a1)   Этаж  __floor__(self)   math.floor(a1)   потолок  __ceil__(self)   math.ceil(a1)

Есть также специальные методы __enter__ и __exit__ для менеджеров контекста, и многих других.

Синтаксис

Параметры

Примечания