Шаг 59.
Python: тонкости программирования.
Классы и ООП. Преобразование строк (использование __repr__) (общие сведения)

    На этом шаге мы приведем общие сведения о дандер-методах и рассмотрим создание одного из них.

    Когда вы определяете собственный класс в Python и затем пытаетесь напечатать один из его экземпляров в консоли (или проверить его в сеансе интерпретатора), вы получаете относительно неудовлетворительный результат. Принятое по умолчанию поведение с преобразованием в строковое значение в стиле "to-string" является примитивным и испытывает недостаток в подробностях:

>>> class Car:
	def __init__(self, color, mileage):
		self.color = color
		self.mileage = mileage

		
>>> my_car = Car('красный', 37281)
>>> print(my_car)
<__main__.Car object at 0x00000182B64C81C0>
>>> my_car
<__main__.Car object at 0x00000182B64C81C0>

    По умолчанию вы получаете лишь строковое значение, содержащее имя класса и идентификатор экземпляра объекта (который в Python является адресом объекта в оперативной памяти). Это лучше, чем ничего, но не очень-то полезно.

    Вы можете попытаться найти обходной путь, непосредственно распечатав атрибуты класса или даже добавив в классы собственный метод to_string():

>>> print(my_car.color, my_car.mileage) 
красный 37281

    Общая идея совершенно верная, но она игнорирует договоренности об именовании и встроенные механизмы, которые Python использует для обработки того, как объекты представляются в виде строк.

    Вместо того чтобы строить свой собственный механизм преобразования строк, будет гораздо лучше, если вы добавите в свой класс дандер-методы __str__ и __repr__. Они представляют собой питоновский способ управления тем, как объекты преобразовываются в строковые значения в различных ситуациях.


См. документацию Python "Модель данных Python": https://docs.python.org/3/reference/datamodel.html.

    Давайте взглянем, как эти методы работают на практике. Для начала мы добавим метод __str__ в класс Car, который мы определили ранее:

>>> class Car:
	def __init__(self, color, mileage):
		self.color = color
		self.mileage = mileage
	def __str__(self):
		return f'{self.color} автомобиль'

    Если сейчас попробовать напечатать или проинспектировать экземпляр Car, то вы получите другой, слегка улучшенный результат:

>>> my_car = Car('красный', 37281)
>>> print(my_car)
красный автомобиль
>>> my_car
<__main__.Car object at 0x00000182B6507280>

    Инспектирование объекта Car в консоли по-прежнему дает предыдущий результат, содержащий идентификатор объекта. Однако распечатка объекта показала строку, возвращенную добавленным нами методом __str__.

    Метод __str__ является одним из дандер-методов Python (с двойным подчеркиванием), и он вызывается, когда вы пытаетесь преобразовать объект в строковое значение посредством различных доступных способов:

>>> print(my_car)
красный автомобиль
>>> str(my_car)
'красный автомобиль'
>>> '{}'.format(my_car)
'красный автомобиль'

    При надлежащей реализации __str__ вам не придется переживать по поводу печати атрибутов объектов непосредственно или написания отдельной функции to_string(). Это питоновский способ управлять преобразованием строк.

    Между прочим, некоторые разработчики предпочитают называть дандер-методы Python "магическими". Но эти методы никоим образом магическими не являются. То, что имена этих методов начинаются и оканчиваются символами двойного подчеркивания, является всего-навсего согласованным правилом именования, которое выделяет их как ключевые функциональные средства языка Python. Он также помогает избежать конфликтов из-за совпадения имен с вашими собственными методами и атрибутами. Конструктор объектов __init__ соблюдает то же самое правило, и в этом нет ничего волшебного или загадочного.

    Не бойтесь использовать дандер-методы Python - они призваны вам помогать.

    На следующем шаге мы сравним методы __str__ и __repr__.




Предыдущий шаг Содержание Следующий шаг