Перейти к основному содержимому

Представление объектов: __str__ и __repr__

Хорошее строковое представление объекта экономит время на отладке и делает выводы понятными. В Python за это отвечают два специальных метода:

  • __repr__ — «официальное» представление для разработчика: максимально точное и однозначное. Часто похоже на конструктор: ClassName(field=value, ...).
  • __str__ — «человеческое» представление для пользователя: коротко и приятно читается.

Если __str__ не определён, Python будет использовать __repr__ и для print(). Списки, словари и отладчики почти всегда используют именно __repr__ элементов.

Базовый пример: оба метода вместе

class HockeyPlayer:
def __init__(self, name, age, team):
self.name = name
self.age = age
self.team = team

def __repr__(self):
# Для разработчика: явно показываем поля, строки — через !r
return f"HockeyPlayer(name={self.name!r}, age={self.age}, team={self.team!r})"

def __str__(self):
# Для пользователя: компактно и по смыслу
return f"{self.name}{self.team}, {self.age} лет"


p = HockeyPlayer('Иван', 17, 'Метеор')
print(p) # __str__
print(repr(p)) # __repr__ явно
print([p]) # контейнеры используют __repr__ элементов
print(f"{p}") # f-строка по умолчанию использует __str__
print(f"{p!r}") # !r берёт __repr__
Иван — Метеор, 17 лет
HockeyPlayer(name='Иван', age=17, team='Метеор')
[HockeyPlayer(name='Иван', age=17, team='Метеор')]
Иван — Метеор, 17 лет
HockeyPlayer(name='Иван', age=17, team='Метеор')

Только __repr__: печать всё равно работает

class PlayerReprOnly:
def __init__(self, name):
self.name = name

def __repr__(self):
return f"PlayerReprOnly(name={self.name!r})"


x = PlayerReprOnly('Иван')
print(x) # падать не будет — print возьмёт __repr__
print(repr(x)) # то же самое явно
PlayerReprOnly(name='Иван')
PlayerReprOnly(name='Иван')

Типичные ошибки: возвращать нужно строку

Оба метода обязаны возвращать именно строку. Любой другой тип — ошибка.

class BadStr:
def __str__(self):
return 123 # ошибка: должен быть str

try:
print(BadStr())
except TypeError as e:
print('Ошибка:', e)
Ошибка: __str__ returned non-string (type int)

Мини-памятка

  • Делайте __repr__ максимально информативным и однозначным (лучше в виде «конструктора»).
  • Делайте __str__ кратким и дружелюбным — для пользовательского вывода.
  • В f-строках f"{obj}" использует __str__, а f"{obj!r}"__repr__.
  • Если __str__ отсутствует, print(obj) покажет __repr__.
  • Списки и другие контейнеры печатают элементы через их __repr__.