Нашли ошибку?
Скачать чистый
урок 1 из 4≈ 15 минупражнения: 0 из 3

Как объект выглядит: __repr__ и __str__

Магические методы — способ встроить свой класс в язык. __repr__ — представление для отладки, __str__ — для людей, repr() и !r в f-строках.

Python запустится при первом выполнении

До сих пор экземпляры своих классов мы не печатали — только их атрибуты. И не зря: без подготовки Python печатает экземпляр так:

>>> latte = Product("Латте", 220)
>>> latte
<__main__.Product object at 0x10a3f2b50>

Имя класса и адрес объекта в памяти — для отладки почти бесполезно, а адрес к тому же меняется при каждом запуске. Научим класс выглядеть понятно.

Магические методы

__init__ — не единственный метод с двумя подчёркиваниями. Таких методов десятки, и все они устроены одинаково: Python вызывает их сам, когда с объектом делают что-то встроенное. len(x) вызывает x.__len__(), print(x) — x.__str__(), а __init__ — создание экземпляра. Их называют магическими методами (special methods; их ещё называют dunder — от double underscore). Объявите такой метод в своём классе — и встроенная операция заработает с вашими объектами.

[ ]len — это вызов __len__
word = "латте"
print(len(word))
print(word.__len__())  # это и делает len
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
5
5

__repr__: представление для отладки

Метод __repr__ возвращает строковое представление (representation) объекта для программиста. Его показывает Jupyter для значения последней строки ячейки, его используют списки и словари, когда печатают свои элементы, и его возвращает встроенная функция repr(). Хорошее представление однозначно и, по возможности, похоже на код, который создаёт такой же объект:

[ ]Product с __repr__
class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

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


latte = Product("Латте", 220)
print(repr(latte))
print([latte, Product("Чай", 120)])
latte  # значение последней строки ячейки показывается через repr
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
Product(name='Латте', price=220)
[Product(name='Латте', price=220), Product(name='Чай', price=120)]
Product(name='Латте', price=220)

Обратите внимание на !r в f-строке: {self.name!r} вставляет не саму строку, а её repr — с кавычками. Без них Product(Латте, 220) уже не похоже на код.

[ ]Упражнение 1Представление напитка решено

Допишите класс Drink: метод __repr__ возвращает строку вида Drink('Латте', 220) — имя класса, название в кавычках и цену.

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

    def __repr__(self):
        ...

__str__: для людей

Метод __str__ возвращает текст для людей — для print, str() и f-строк. Он не обязан быть похож на код. Если __str__ в классе нет, Python использует __repr__:

[ ]print, str() и значение в ячейке
class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

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

    def __str__(self):
        return f"{self.name} за {self.price} ₽"


latte = Product("Латте", 220)
print(latte)
print(str(latte), "|", repr(latte))
print(f"Сегодня советуем: {latte}")
latte
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
Латте за 220 ₽
Латте за 220 ₽ | Product(name='Латте', price=220)
Сегодня советуем: Латте за 220 ₽
Product(name='Латте', price=220)
[ ]Упражнение 2Заказ для журнала и для кассы решено

Допишите класс Order: __repr__ возвращает Order(17, 640) — номер и сумму, а __str__ — текст для кассира: Заказ №17 на 640 ₽.

class Order:
    def __init__(self, number, total):
        self.number = number
        self.total = total

    def __repr__(self):
        ...

    def __str__(self):
        ...

Вопрос

У класса Order из упражнения есть и __str__, и __repr__. Что напечатает print([Order(17, 640)])?

repr и str в f-строках

В f-строке {x} даёт str(x), а {x!r} — repr(x). Первое — для сообщений людям, второе — для журналов и сообщений об ошибках, где важно точно видеть значение:

[ ]Упражнение 3Два сообщения решено

Для заказа order составьте две строки: message — "Готов: Заказ №17 на 640 ₽" для экрана выдачи (через __str__) и log — "создан Order(17, 640)" для журнала (через __repr__). Используйте f-строки с самим объектом, без обращения к его атрибутам.

order = Order(17, 640)
message = ...
log = ...

Правило на будущее: у каждого своего класса должен быть __repr__ — отладка без него мучительна. __str__ — когда объекту нужен отдельный «человеческий» вид.

Нашли ошибку?