Методы __str__() и __repr__() в Python

В этой статье мы поговорим о специальных методах __str__() и __repr__() в модели данных Python. Методы __str__() и __repr__() могут быть полезны при отладке кода Python путем логирования или вывода полезной информации об объекте.

Читайте также: Использование модуля logging в Python 3

Специальные методы Python начинаются и заканчиваются двойным подчеркиванием и потому неофициально называются dunder методами (где dunder – сокращение от double underscore). Данные методы являются базовыми для встроенных операторов и функций Python. Прямого вызова методов dunder следует избегать;  лучше сначала реализовывать их в классах, а затем использовать встроенные функции, которые их вызывают, типа str() и repr().

Разница между __str__() и __repr__()

Метод __str__() возвращает удобочитаемое (или неформальное) строковое представление объекта. Этот метод вызывается встроенными функциями print(), str() и format(). Если вы не определяете метод __str__() для класса, то встроенная реализация объекта будет вызывать метод __repr__().

Метод __repr__() возвращает более информативное (официальное) строковое представление объекта. Этот метод вызывается встроенной функцией repr(). Если возможно, возвращаемая строка должна быть представлена валидным выражением Python, которое можно использовать для воссоздания объекта. В любом случае строка должна быть информативной и однозначной.

Как правило, строка __str__() предназначена для пользователей, а __repr__() — для разработчиков.

Примеры встроенных __str__() и __repr__() 

Примеры в этом разделе прямо вызывают методы __str__() и __repr__() в демонстрационных целях.

Класс datetime.datetime — это встроенный класс Python, который по умолчанию реализует методы __str__() и __repr__().

В следующем примере кода показаны строки, возвращаемые стандартной реализацией методов __str__() и __repr__() для объекта datetime.datetime:

import datetime

mydate = datetime.datetime.now()

print("__str__() string: ", mydate.__str__())
print("str() string: ", str(mydate))

print("__repr__() string: ", mydate.__repr__())
print("repr() string: ", repr(mydate))

Вывод будет следующим: 

__str__() string:  2023-01-27 09:50:37.429078
str() string:  2023-01-27 09:50:37.429078
__repr__() string:  datetime.datetime(2023, 1, 27, 9, 50, 37, 429078)
repr() string:  datetime.datetime(2023, 1, 27, 9, 50, 37, 429078)

Вывод показывает, что функция str() вызывает метод __str__() и возвращает удобочитаемую строку, а функция repr() вызывает метод __repr__() и возвращает более информативную строку, которую можно использовать для воссоздания объекта. Фактически для создания нового объекта из строки вы можете использовать функцию repr() с функцией eval():

import datetime

mydate1 = datetime.datetime.now()
mydate2 = eval(repr(mydate1))

print("mydate1 repr() string: ", repr(mydate1))
print("mydate2 repr() string: ", repr(mydate2))

print("the values of the objects are equal: ", mydate1==mydate2)

Получим следующее: 

mydate1 repr() string:  datetime.datetime(2023, 1, 26, 9, 43, 24, 479635)
mydate2 repr() string:  datetime.datetime(2023, 1, 26, 9, 43, 24, 479635)
the values of the objects are equal:  True

Код в предыдущем примере создает объект mydate2 из строки repr() для mydate1, а затем проверяет, равны ли значения обоих объектов.

Примеры __str__() и __repr__() в новых классах

Когда вы создаете класс, вы должны реализовать как минимум метод __repr__(), чтобы возвращать полезную информацию, когда встроенные функции используют __repr__().

Следующий класс не реализует ни метод __str__(), ни __repr()__:

class Ocean:

    def __init__(self, sea_creature_name, sea_creature_age):
        self.name = sea_creature_name
        self.age = sea_creature_age

c = Ocean('Jellyfish', 5)

print(str(c))
print(repr(c))

При использовании функций str() и repr() вывод будет таким: 

<__main__.Ocean object at 0x102892860>
<__main__.Ocean object at 0x102892860>

В предыдущем примере показано, что реализация __repr()__ по умолчанию возвращает строку, содержащую только класс и идентификатор объекта в шестнадцатеричном формате, что не очень полезно. Обратите внимание, что str() и repr() возвращают одно и то же: такое происходит, если метод __str__() не реализован — тогда функция str() вызывает метод __repr__().

Обновите класс Ocean, добавив реализации методов __str__() и __repr__():

class Ocean:

    def __init__(self, sea_creature_name, sea_creature_age):
        self.name = sea_creature_name
        self.age = sea_creature_age

    def __str__(self):
        return f'The creature type is {self.name} and the age is {self.age}'

    def __repr__(self):
        return f'Ocean(\'{self.name}\', {self.age})'

c = Ocean('Jellyfish', 5)

print(str(c))
print(repr(c))

В результате получим: 

The creature type is Jellyfish and the age is 5
Ocean('Jellyfish', 5)\

Реализация __str__() в предыдущем примере возвращает удобочитаемую строку, предоставляющую пользователю релевантные сведения об объекте. В то же время реализация __repr__() возвращает строку, являющуюся допустимым выражением Python, которое можно использовать для воссоздания объекта: Ocean(‘Jellyfish’, 5). В примере используются f-строки, но вы можете форматировать строки так, как удобнее вам.

Заключение

В этой статье мы на примерах продемонстрировали различия между специальными методами __str__() и __repr__() и реализовали их в классах, чтобы их не нужно было вызывать напрямую.

Tags:

Добавить комментарий