В чем разница между методами __str__ и __repr__ в Python

Ответ

В Python магические методы __str__ и __repr__ определяют строковое представление объекта, но служат разным целям и аудиториям.

  • __repr__(self)для разработчиков.

    • Цель: Создать недвусмысленное, официальное представление объекта, которое идеально подходит для отладки.
    • Правило хорошего тона: Строка, возвращаемая __repr__, должна быть таким кодом, который может воссоздать объект. То есть eval(repr(obj)) == obj.
    • Когда вызывается: Функцией repr(obj) и при выводе объекта в интерактивной консоли.
  • __str__(self)для пользователей.

    • Цель: Создать читаемое, неформальное представление объекта для конечного пользователя.
    • Когда вызывается: Функцией str(obj) и конструкцией print(obj).

Ключевое правило: Если метод __str__ не реализован, Python автоматически использует __repr__ вместо него. Поэтому рекомендуется всегда реализовывать как минимум __repr__.

Пример

import datetime

class User:
    def __init__(self, username, created_at):
        self.username = username
        self.created_at = created_at

    # Представление для отладки: полное и однозначное
    def __repr__(self):
        return f"User(username='{self.username}', created_at={repr(self.created_at)})"

    # Представление для пользователя: краткое и понятное
    def __str__(self):
        return f"Пользователь: {self.username}"

user = User('admin', datetime.datetime.now())

# Вызов в консоли или repr()
# >> user
# User(username='admin', created_at=datetime.datetime(2023, 10, 27, 10, 30, 0))
print(repr(user))

# Вызов print() или str()
# >> print(user)
# Пользователь: admin
print(str(user))

Ответ 18+ 🔞

А, вот эта тема про __str__ и __repr__! Ну что, дружок-пирожок, давай разберёмся, пока не поехала крыша окончательно.

Представь себе, что у тебя есть объект. Какой-нибудь, блядь, user = User('admin'). И ты его в консольку выводишь. И тут начинается магия, ёпта! А точнее, магические методы.

Вот смотри, есть два этих засранца:

  • __repr__(self) — это, сука, для нас, для разработчиков. Как будто ты наливаешь себе кофе в три часа ночи и пытаешься понять, почему всё сломалось. Его задача — выдать такую строчку, чтобы ты, мудак, сразу понял, что это за объект. Идеально — чтобы эту строчку можно было скопировать, вставить в код, и получился бы такой же объект. eval(repr(obj)) == obj — вот это святое правило, блядь! Вызывается, когда пишешь repr(obj) или просто смотришь на объект в консоли.

  • __str__(self) — это уже для пользователей, для этих, блядь, мирных жителей. Чтобы им красиво и понятно показать: «О, смотрите, это пользователь Вася!». Не надо тут никаких дат создания и внутренних айдишников. Просто «Пользователь: admin». Вызывается, когда делаешь print(obj) или str(obj).

А теперь главный прикол, в рот меня чих-пых! Если ты такой умный и не написал __str__, то Python, хитрая жопа, возьмёт и подставит вместо него __repr__. Поэтому, если реализовывать что-то одно — делай __repr__. Но лучше оба, ёпта.

Смотри, как это выглядит на практике

import datetime

class User:
    def __init__(self, username, created_at):
        self.username = username
        self.created_at = created_at

    # Это для отладки, чтобы я, обалдевший, мог всё понять
    def __repr__(self):
        return f"User(username='{self.username}', created_at={repr(self.created_at)})"

    # А это уже для красивого вывода в лог или интерфейс
    def __str__(self):
        return f"Пользователь: {self.username}"

user = User('admin', datetime.datetime.now())

# Вот это вызовет __repr__ — полная техническая информация, как в черном ящике
# User(username='admin', created_at=datetime.datetime(2023, 10, 27, 10, 30, 0))
print(repr(user))

# А вот это вызовет __str__ — коротко и ясно для всех
# Пользователь: admin
print(str(user))

Вот и вся разница, блядь. Один для дебага, другой — для красоты. Не перепутай, а то пользователям вместо «Привет, Иван» вылезет какая-нибудь User object at 0x7f8b1d2c3d90, и они тебе такого наговорят, мало не покажется.