Курс по Python ООП: https://stepik.org/a/116336
На этом занятии я
расскажу о, так называемых, магических методах, которые определены в каждом
классе и записываются через два подчеркивания вначале и в конце имен, например,
так:
__str__, __repr__
Как я говорил, их
еще называют
dunder-методами (от
англ. сокращения double underscope)
Каждый магический
метод автоматически срабатывает в определенный момент времени, например:
- __str__() – магический
метод для отображения информации об объекте класса для пользователей (например,
для функций print, str);
- __repr__() – магический
метод для отображения информации об объекте класса в режиме отладки (для
разработчиков).
Чтобы лучше
понять, как работают эти методы, объявим класс для описания кошек:
class Cat:
def __init__(self, name):
self.name = name
Перейдем в
консоль Python, скопируем
(определим) этот класс. Затем, создадим его экземпляр:
При выводе cat, увидим
служебную информацию:
<ex1.Cat object at 0x0495D028>
Если нам нужно
ее как-то переопределить и отобразить в другом виде (формате), то, как раз для
этого используются магические методы __str__ и __repr__. Давайте для
начала переопределим метод __repr__ и посмотрим, как это отразится на
выводе служебной информации о классе:
def __repr__(self):
return f"{self.__class__}: {self.name}"
Обратите
внимание, этот метод должен возвращать строку, поэтому здесь записан оператор return и формируемая
строка. Что именно возвращать, мы решаем сами, в данном случае – это название
класса и имя кошки.
Переопределим измененный
класс Cat. И, смотрите,
теперь при создании экземпляра мы видим другую информацию при его выводе:
<class
'ex1.Cat'>: Васька
Как раз то, что
определили в магическом методе __repr__. То же самое увидим и при
использовании функции print и str. По идее, здесь
должен отрабатывать другой магический метод __str__, но так как
он у нас еще не переопределен, то автоматически выполняется метод __repr__.
Давайте добавим
второй магический метод __str__ и посмотрим, как это повлияет на
отображение данных:
def __str__(self):
return f"{self.name}"
Снова
переопределим класс Cat, создадим его экземпляр и при отображении ссылки:
по-прежнему
будем видеть служебную информацию от метода __repr__. Однако,
если выполнить отображение экземпляра класса через print или str, то будет
срабатывать уже второй метод __str__. Вот в этом отличие этих двух
магических методов.
Магические методы __len__ и __abs__
Следующие два
магических метода:
- __len__() – позволяет
применять функцию len() к экземплярам класса;
- __abs__() - позволяет
применять функцию abs() к экземплярам класса.
Их использование
достаточно простое и очевидное. Давайте для примера представим, что у нас есть
класс Point, который может
хранить произвольный вектор координат точек, и определим его так:
class Point:
def __init__(self, *args):
self.__coords = args
А, далее, по
программе нам бы хотелось определять размерность координат с помощью функции len(), следующим
образом:
p = Point(1, 2)
print(len(p))
Если сейчас
запустить программу, то увидим ошибку, так как функция len не применима к
экземплярам классов по умолчанию. Как вы уже догадались, чтобы изменить это
поведение, можно переопределить магический метод __len__() и в нашем
случае это можно сделать так:
def __len__(self):
return len(self.__coords)
Смотрите, мы
здесь возвращаем размер списка __coords и если после этого запустить
программу, то как раз это значение и будет выведено в консоль. То есть,
магический метод __len__ указал, что нужно возвращать, в момент применения
функции len() к экземпляру
класса. Как видите, все просто и очевидно.
Следующий
магический метод __abs__ работает аналогичным образом, только активируется
в момент вызова функции abs для экземпляра класса, например, так:
Опять же, если
сейчас выполнить программу, то увидим ошибку, т.к. функция abs не может быть
напрямую применена к экземпляру. Но, если переопределить магический метод:
def __abs__(self):
return list( map(abs, self.__coords) )
который
возвращает список из абсолютных значений координат точки, то программа
отработает в штатном режиме и мы увидим ожидаемый результат.
Вот так можно
использовать эти два магических метода. Я, надеюсь, из этого занятия вы узнали,
зачем нужны и как можно реализовывать в своих классах четыре магических метода:
__str__,
__repr__, __len__, __abs__
Курс по Python ООП: https://stepik.org/a/116336