Документация по Python

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

В: Документация по Python

Введение

Примеры

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

Магические (также называемые 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__ для менеджеров контекста, и многих других.

Синтаксис

Параметры

Примечания

Еще от кодкамп
Замечательно! Вы успешно подписались.
Добро пожаловать обратно! Вы успешно вошли
Вы успешно подписались на кодкамп.
Срок действия вашей ссылки истек.
Ура! Проверьте свою электронную почту на наличие волшебной ссылки для входа.
Успех! Ваша платежная информация обновлена.
Ваша платежная информация не была обновлена.