Чем отличаются __str__ от __repr__?python-31

Эти "магические методы" служат для строкового представления объектов, но имеют разные цели и поведение. Понимание их различий критически важно для написания корректных Python-классов.

Основное назначение

class Example:
    def __init__(self, data):
        self.data = data

    def __str__(self):
        return f"Example: {self.data}"

    def __repr__(self):
        return f"Example(data={repr(self.data)})"

__str__:

  • Для пользователя: Читаемое, "красивое" представление объекта
  • Используется функциями str() и print()
  • Должен быть понятным для конечного пользователя

__repr__:

  • Для разработчика: Однозначное и точное представление объекта
  • Используется функцией repr(), а также при отображении в REPL
  • Идеально должно быть валидным Python-кодом для воссоздания объекта

Ключевые различия

Характеристика __str__ __repr__
Целевая аудитория Конечные пользователи Разработчики
Использование print(obj), str(obj) repr(obj), REPL, отладка
Требования Читаемость Однозначность
Идеальный вывод "Понятный текст" Python-код для воссоздания
Обязательность Опциональный Рекомендуется для всех классов

Поведение по умолчанию

Если __str__ не определен, Python использует __repr__ как fallback:

class DefaultExample:
    def __repr__(self):
        return "DefaultExample()"

obj = DefaultExample()
print(obj)  # Выведет: DefaultExample() - использует __repr__

Практические примеры

1. Пример с датой

from datetime import datetime

now = datetime.now()
print(str(now))   # '2023-05-15 14:30:00' - для пользователя
print(repr(now))  # 'datetime.datetime(2023, 5, 15, 14, 30)' - для разработчика

2. Кастомный класс

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

    def __str__(self):
        return f"{self.name} - ${self.price:.2f}"

    def __repr__(self):
        return f"Product(name={repr(self.name)}, price={self.price})"

p = Product("Laptop", 999.99)
print(p)          # Laptop - $999.99
print(repr(p))    # Product(name='Laptop', price=999.99)

Рекомендации по реализации

  1. Для __repr__:

    • Старайтесь возвращать строку, которую можно использовать с eval()
    • Включайте все значимые атрибуты
    • Используйте repr() для строковых атрибутов
  2. Для __str__:

    • Делайте вывод максимально понятным
    • Можно опускать технические детали
    • Используйте форматирование для лучшей читаемости
  3. Общее правило:

    • Всегда определяйте __repr__
    • __str__ - опционально, если нужен особый пользовательский вывод

Особые случаи

Коллекции :

items = [1, 2, 3]
print(str(items))  # '[1, 2, 3]'
print(repr(items)) # '[1, 2, 3]' (для простых типов может совпадать)

Отладочный вывод :

class Debuggable:
    def __repr__(self):
        return f"{self.__class__.__name__}(id={id(self)})"

Резюмируем

  1. __str__ - для "красивого" вывода (пользователи), __repr__ - для точного (разработчики)
  2. __repr__ должен быть максимально информативным и желательно воспроизводимым
  3. Если не определен __str__, Python использует __repr__
  4. Всегда определяйте __repr__ для своих классов
  5. Для встроенных типов str() и repr() могут давать одинаковый вывод

Правило из официальной документации:

__repr__ должен быть однозначным, а __str__ - читаемым.