Что такое перегрузка операторов python
Перегрузка оператора в Python
Перегрузка операторов в Python позволяет нам использовать математические, логические и побитовые операторы для объектов, как и любой примитивный тип данных.
Например, вы можете легко сложить два числа 3 и 5 с помощью оператора +, т.е. 3 + 5. И результат будет 8.
Но что, если вы хотите добавить два круга (объект класса Circle) и создать круг с двойным радиусом? Или что, если вы хотите добавить две точки декартовой сетки, чтобы получить еще одну точку с тем же оператором «+»? Перегрузка операторов Python позволяет выполнять такие же операции.
Пример перегрузки оператора
Теперь давайте посмотрим на пример перегрузки математического оператора.
Строки с 1 по 4 указывают объявление класса GridPoint и определение метода конструктора. Давайте посмотрим на строки 6 и 7.
Когда мы используем оператор ‘+’ в качестве операции математического сложения, неявно вызывается метод __add __().
Итак, если мы хотим добавить два объекта класса GridPoint, мы должны заново определить этот метод. Итак, здесь нам нужно создать еще один экземпляр класса GridPoint, значение x которого является суммой x в двух экземплярах GridPoint вокруг оператора ‘+’, а значение y также является суммированием y в двух экземплярах GridPoint вокруг ‘ + ‘оператор.
Строки с 9 по 12 определяют метод __str __(), который вызывается, когда мы пытаемся напечатать объект. Это тоже встроенный метод. Но мы собираемся перегрузить метод, чтобы он печатал в нашем указанном формате.
В строках 14 и 15 мы создали два объекта GridPoint, а именно point1 и point2. Теперь посмотрите Строку 16. Два экземпляра класса GridPoint добавляются с помощью оператора «+» и назначаются, как другой экземпляр GridPoint. В этом вам поможет перегрузка операторов Python. Так что не удивляйтесь, когда 17-я строка покажет результат, как на изображении ниже.
Список математических операторов
Вот список операторов, которые можно перегрузить и аналогичным образом использовать с перегрузкой операторов.
Оператор | Описание | Метод |
+ | Дополнение | __add __ (self, other) |
— | Вычитание | __sub __ (self, other) |
* | Умножение | __mul __ (self, other) |
/ | Истинное деление | __truediv __ (self, other) |
// | Подразделение этажей | __floordiv __ (self, other) |
% | Остаток | __mod __ (self, other) |
** | Мощность | __pow __ (self, other) |
& | Побитовое AND | __and __ (self, other) |
| | Побитовое OR | __or __ (self, other) |
^ | Побитовое исключающее XOR | __xor __ (self, other) |
Перегрузка операторов отношения
Операторы отношения перегружаются в Python очень похожим образом. Но разница в том, что эти операторы часто возвращают true и false вместо другого экземпляра объекта. Давайте работать с примером.
Посмотрите на строку 6, где загружен оператор «больше». Обычный оператор ‘>’ возвращает истину, если операнд в его левой части больше, чем в правом. Мы собираемся использовать это свойство для сравнения двух экземпляров класса GridPoint.
Другие операторы отношения
Вот список реляционных операторов, которые можно перегрузить таким же образом.
Перегрузка операторов
Перегрузка операторов в Python – это возможность с помощью специальных методов в классах переопределять различные операторы языка. Имена таких методов включают двойное подчеркивание спереди и сзади.
Мы уже использовали ряд методов перегрузки операторов. Это
__init__() – конструктор объектов класса, вызывается при создании объектов
__del__() – деструктор объектов класса, вызывается при удалении объектов
__str__() – преобразование объекта к строковому представлению, вызывается, когда объект передается функциям print() и str()
__add__() – метод перегрузки оператора сложения, вызывается, когда объект участвует в операции сложения будучи операндом с левой стороны
__setattr__() – вызывается, когда атрибуту объекта выполняется присваивание
В Python много других методов перегрузки операторов. В этом уроке рассмотрим еще несколько.
На самом деле перегрузка операторов в пользовательских классах используется не так часто, если не считать конструктора. Но сам факт наличия такой особенности объектно-ориентированного программирования, требует отдельного рассмотрения темы.
Пусть будет класс-агрегат B, содержащий в списке объекты класса A:
Чтобы получить элемент списка, несомненно, мы можем обратиться по индексу к полю aList :
Однако куда интереснее извлекать элемент по индексу из самого объекта, а не из его поля:
Метод __call__() автоматически вызывается, когда к объекту обращаются как к функции. Например, здесь во второй строке произойдет вызов метода __call__() некогоКласса :
В этом примере с помощью конструктора класса при создании объектов устанавливается их цвет. Если требуется его поменять, то достаточно обратиться к объекту как к функции и в качестве аргумента передать новый цвет. Такой обращение автоматически вызовет метод __call__(), который, в данном случае, изменит атрибут color объекта.
В Python кроме метода __str__() есть схожий с ним по поведению, но более «низкоуровневый» метод __repr__(). Оба метода должны возвращать строку.
Если в классе есть только метод __str__(), то при обращении к объекту в интерпретаторе без функции print(), он не будет вызываться:
Попытка преобразования объекта в строку с помощью встроенной функции str() также вызывает метод __str__(). То есть скорее всего метод __str__() перегружает не функцию print(), а функцию str(). Функция же print() так устроена, что сама вызывает str() для своих аргументов.
В Python есть встроенная функция repr(), которая также как str() преобразует объект в строку. Но «сырую» строку. Что это значит, попробуем понять с помощью примера:
Функция eval преобразует переданную строку в программный код, который тут же выполняется. Функция print() выполняет переход на новую строку, если встречает символ \n. Функция repr() выполняет действия, направленные на своего рода защиту строки от интерпретации, оставляет ее «сырой», т. е. в исходном виде. Еще раз:
Однако для большинства случаев различия между repr() и str() не важны. Поэтому в классах проще определять один метод __repr__(). Он будет вызываться для всех случаев преобразования к строке:
Если же нужен различающийся вывод данных, тогда в классе следует определить оба метода перегрузки операторов преобразования к строке.
Практическая работа
Напишите класс Snow по следующему описанию.
В конструкторе класса инициируется поле, содержащее количество снежинок, выраженное целым числом.
Класс включает методы перегрузки арифметических операторов: __add__() – сложение, __sub__() – вычитание, __mul__() – умножение, __truediv__() – деление. В классе код этих методов должен выполнять увеличение или уменьшение количества снежинок на число n или в n раз. Метод __truediv__() перегружает обычное (/), а не целочисленное (//) деление. Однако пусть в методе происходит округление значения до целого числа.
Класс включает метод makeSnow(), который принимает сам объект и число снежинок в ряду, а возвращает строку вида «*****\n*****\n*****…», где количество снежинок между ‘\n’ равно переданному аргументу, а количество рядов вычисляется, исходя из общего количества снежинок.
Вызов объекта класса Snow в нотации функции с одним аргументом, должен приводить к перезаписи значения поля, в котором хранится количество снежинок, на переданное в качестве аргумента значение.
Курс с примерами решений практических работ:
android-приложение, pdf-версия
С. Шапошникова © 2021
Объектно-ориентированное программирование на Python
Перегрузка операторов
На этом занятии рассмотрим способы перегрузки операторов в классах. Что это такое? Давайте для примера создадим такой простой класс Clock (часы). В каждом экземпляре этого класса будем хранить время в виде секунд, отсчитывая от 00:00 часов ночи. Соответственно, число секунд не должно превышать значения:
24∙60∙60 = 86400 (число секунд в одном дне)
Поэтому, в инициализаторе класса перед присвоением выполним операцию вычисления остатка от деления на это число:
Затем, реализуем метод getFormatTime(), который возвращает указанное время в формате:
Получаем такую реализацию класса:
И, далее, мы можем его вот так создавать и выводить время в консоль:
Но теперь предположим, что мы хотели бы складывать времена вот так:
Если сейчас запустить программу, то увидим ожидаемую ошибку, что два таких класса складывать нельзя. И вот для таких случаев в Python предусмотрена возможность перегрузки операторов, чтобы они стали делать нужную нам операцию. В данном случае нужно перегрузить оператор сложения («+»). В действительности, когда он выполняется с классами, то в классе вызывается специальный метод
вот его нам и нужно переопределить. Запишем в классе Clock следующие строки:
и добавим геттер getSeconds:
Все, теперь при выполнении оператора сложения будет формироваться новый экземпляр класса Clock с суммой секунд от правого и левого операндов. Запускаем программу и видим, что все работает как мы и хотели.
Мало того, мы можем вычислять и вот такие операции:
То есть, мы получили универсальный оператор сложения для часов.
Теперь посмотрим как можно перегрузить операторы типа
для этого нужно переопределить метод
Сделаем это следующим образом:
Смотрите, мы здесь меняем значение секунд в самом экземпляре класса self и возвращаем этот же экземпляр, не создавая нового. В итоге операцию:
можно представить так:
Или же все наши перегруженные операторы записать и так:
Как это будет в деталях работать, я думаю, вы уже догадались. По аналогии могут быть перегружены и другие подобные операторы. Вот их краткий список:
По аналогии можно перегружать операторы сравнения. Например, мы хотим сравнить время для двух часов:
Для этого в классе Clock нужно переопределить метод:
Тогда при одинаковом числе секунд:
оператор == возвратит True:
Или же, метод eq можно записать в более краткой форме:
Это будет одно и то же (по результату).
Далее, сравнение на неравенство можно сделать так:
Как видите, это все работает довольно просто и очевидно. Основные операторы сравнения, следующие:
__add__(self, other) | + |
__sub__(self, other) | – |
__mul__(self, other) | * |
__truediv__(self, other) | / |
__mod__(self, other) | % |
__lt__(self, other) | |
__eq__(self, other) | == |
__ne__(self, other) | != |
__gt__(self, other) | > |
__ge__(self, other) | >= |
Вывод
Python поддерживает как перегрузку функций, так и перегрузку операторов. При перегрузке функций мы можем использовать одно и то же имя для многих функций Python, но с разным количеством или типами параметров. С помощью перегрузки операторов мы можем изменить значение оператора Python в рамках класса.
Перегрузка операторов в Python
Введение
Примеры
Методы магии / Дандер
Магические (также называемые dunder как аббревиатура от двойного подчеркивания) методы в Python имеют ту же цель, что и перегрузка операторов в других языках. Они позволяют классу определять свое поведение, когда он используется в качестве операнда в выражениях унарных или бинарных операторов. Они также служат реализациями, вызываемыми некоторыми встроенными функциями.
Рассмотрим эту реализацию двумерных векторов.
Тип контейнера и последовательности
Вызываемые типы
Обработка невыполненного поведения
Перегрузка оператора
Ниже приведены операторы, которые могут быть перегружены в классах, а также необходимые определения методов и пример использования оператора в выражении.
NB Использование other в качестве имени переменной не является обязательным, но считается нормой.
Побитовое НЕ __invert__(self)
Необязательный параметр по modulo для __pow__ используется только в pow встроенной функции.
а также соответствующая версия Inplace, начиная с __i :
Поскольку в этих методах нет ничего особенного, многие другие части языка, части стандартной библиотеки и даже сторонние модули самостоятельно добавляют магические методы, такие как методы для приведения объекта к типу или проверки свойств объекта. Например, встроенная 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__ для менеджеров контекста, и многих других.
Синтаксис
Параметры
Примечания
Научим основам Python и Data Science на практике
Это не обычный теоритический курс, а онлайн-тренажер, с практикой на примерах рабочих задач, в котором вы можете учиться в любое удобное время 24/7. Вы получите реальный опыт, разрабатывая качественный код и анализируя реальные данные.
- Что такое смарт часы и для чего они нужны взрослым
- Что такое план конспект статьи