Как использовать методы __str__() и __repr__() в Python

    Команда Simple-Server
    03.06.2026
    12 мин

    Материал подготовлен командой Simple-Server для администраторов VPS и выделенных серверов. Команды и пути проверяйте на тестовой машине перед production.

    Разница между str() и repr()

    Методы связаны между собой, однако имеют существенные различия по части вывода дополнительной информации:

    • Метод __str__() возвращает фактическое значение переменной в формате строки. Он менее информативен. А еще вызывается функциями print(), str(), format().

    Метод __str__() возвращает фактическое значение переменной в формате строки. Он менее информативен. А еще вызывается функциями print(), str(), format().

    • Метод __repr__() возвращает репрезентируемое значение переменной в формате кода. Он более информативен. А еще вызывается функцией repr().

    Метод __repr__() возвращает репрезентируемое значение переменной в формате кода. Он более информативен. А еще вызывается функцией repr().

    При этом, в отличие от __str__(), результат метода __repr__() можно использовать для воссоздания переменной с помощью функции eval(), которая выполняет код (выражения языка Python) в формате строки.

    Грубо говоря, возвращаемое значение метода __str__() ориентировано на пользователя, в то время как результат функции __repr__() больше предназначен для разработчика.**
    **

    Пример: встроенные типы данные

    Для более глубокого понимания отличия между обоими методами лучше всего привести простой, но наглядный пример:

    variableInt = 13 # переменная с целочисленным значением variableString = "13" # переменная со строковым значением # вывод в консоль типов переменных print(type(variableInt)) print(type(variableString)) # вывод в консоль целочисленной переменной print(variableInt.__str__()) print(variableInt.__repr__()) # вывод в консоль строковой переменной print(variableString.__str__()) print(variableString.__repr__())

    Консольный вывод этого примера будет следующим:

    <class 'int'> <class 'str'> 13 13 13 '13'

    Во-первых, переменные однозначно имеют разные типы — целочисленный и строковый.

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

    Чтобы понять причину такого поведения, можно немного расширить показанный выше пример:

    variableInt = 13 variableString = "13" print(type(variableInt)) print(type(variableString)) print(variableInt.__str__()) print(variableInt.__repr__()) print(variableString.__str__()) print(variableString.__repr__()) # создание новых переменных (целочисленной и строковой) с помощью функции eval() на основе дополнительной информации, репрезентирующей их variableIntNew = eval(variableInt.__repr__()) variableStringNew = eval(variableString.__repr__()) # вывод в консольный терминал типов новых переменных print(type(variableIntNew)) print(type(variableStringNew)) # вывод в консольный терминал значения новых переменных print(variableIntNew) print(variableStringNew)

    На этот раз вывод в консольном терминале будет уже таким:

    <class 'int'> <class 'str'> 13 13 13 '13' <class 'int'> <class 'str'> 13 13

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

    Однако если бы вместо __repr__() использовалась __str__(), то такой результат не был бы достигнут — вместо новой строковой появилась бы новая целочисленная переменная:

    variableInt = 13 variableString = "13" print(type(variableInt)) print(type(variableString)) variableIntNew = eval(variableInt.__str__()) variableStringNew = eval(variableString.__str__()) print(type(variableIntNew)) print(type(variableStringNew))

    Вывод в консольный терминал после запуска этого примера будет следующим:

    <class 'int'> <class 'str'> <class 'int'> <class 'int'>

    Как видно, обе новые переменные имеют один и тот же тип — целочисленный. Очевидно, это не то поведение, которое хотелось достигнуть.

    Таким образом, можно сформулировать разницу между обоими методами довольно простым языком:

    • Функция __str__() возвращает текущее значение переменной.

    Функция __str__() возвращает текущее значение переменной.

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

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

    import datetime # импорт стандартного модуля для работы с датой и временем dateNow = datetime.datetime.now() # создание переменной типа даты и времени, которая будет содержать текущее время print("Тип:", type(dateNow)) # вывод в консольный терминал типа переменной print("Значение:", dateNow.__str__()) # вывод в консольный терминал значения переменной print("Репрезентация:", dateNow.__repr__()) # вывод в консольный терминал репрезентации переменной

    Консольный вывод этого примера будет содержать дополнительную информацию о переменной:

    Тип: <class 'datetime.datetime'> Значение: 2024-12-20 05:31:58.749833 Репрезентация: datetime.datetime(2024, 12, 20, 5, 31, 58, 749833)

    На примере библиотечного класса (в отличие от встроенных типов) хорошо видно, насколько сильно значение переменной (__str__()) может отличатся от ее репрезентации (__repr__()), которая может быть выполнена в качестве выражения Python.

    Благодаря такому поведению показанный код можно усложнить, добавив операцию с уже знакомой функцией eval(), создающую копию оригинальной переменной в данном конкретном случае:

    import datetime dateNow = datetime.datetime.now() print("Тип:", type(dateNow)) print("Значение:", dateNow.__str__()) print("Репрезентация:", dateNow.__repr__()) print("") # вывод в консольный терминал пустой строки для визуального разделения двух других выводов dateNowSecond = eval(dateNow.__repr__()) # создаем копию переменной времени на основе репрезентации оригинальной переменной print("Тип:", type(dateNowSecond)) print("Значение:", dateNowSecond.__str__()) print("Репрезентация:", dateNowSecond.__repr__())

    Вывод в консольный терминал при запуске этого примера будет следующим:

    Тип: <class 'datetime.datetime'> Значение: 2024-12-20 11:52:47.243953 Репрезентация: datetime.datetime(2024, 12, 20, 11, 52, 47, 243953) Тип: <class 'datetime.datetime'> Значение: 2024-12-20 11:52:47.243953 Репрезентация: datetime.datetime(2024, 12, 20, 11, 52, 47, 243953)

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

    Аналогично примерам с базовыми типами данных, такого результата нельзя достигнуть с помощью метода __str__():

    import datetime dateNow = datetime.datetime.now() print("Тип:", type(dateNow)) print("Значение:", dateNow.__str__()) print("Репрезентация:", dateNow.__repr__()) print("") dateNowSecond = eval(dateNow.__str__()) # создаем копию переменной времени на основе значения оригинальной переменной print("Тип:", type(dateNowSecond)) print("Значение:", dateNowSecond.__str__()) print("Репрезентация:", dateNowSecond.__repr__())

    После запуска этого примера в консольном терминале возникнет ошибка:

    Тип: <class 'datetime.datetime'> Значение: 2024-12-20 21:32:20.088363 Репрезентация: datetime.datetime(2024, 12, 20, 21, 32, 20, 88363) Traceback (most recent call last): File "/home/jdoodle.py", line 11, in <module> dateNowSecond = eval(dateNow.__str__()) # создаем копию переменной времени на основе значения оригинальной переменной ^^^^^^^^^^^^^^^^^^^^^^^ File "<string>", line 1 2024-12-20 21:32:20.088363 ^^ SyntaxError: invalid syntax

    Это происходит потому, что эта запись:

    dateNowSecond = eval(dateNow.__str__())

    Неявно преобразуется в эту:

    dateNowSecond = 2024-12-20 21:32:20.088363

    Разумеется, такое выражение некорректно в языке Python.

    Как минимум в показанном примере выполняемый внутри функции eval() код можно поместить в одинарные кавычки:

    import datetime dateNow = datetime.datetime.now() print("Тип:", type(dateNow)) print("Значение:", dateNow.__str__()) print("Репрезентация:", dateNow.__repr__()) print("") dateNowSecond = eval("'" + dateNow.__str__() + "'") # выражение обернуто в одинарные кавычки print("Тип:", type(dateNowSecond)) print("Значение:", dateNowSecond.__str__()) print("Репрезентация:", dateNowSecond.__repr__())

    Это позволит избежать ошибки, но исказит требуемое поведение программы. Консольный вывод будет таким:

    Тип: <class 'datetime.datetime'> Значение: 2024-12-20 21:37:59.112795 Репрезентация: datetime.datetime(2024, 12, 20, 21, 37, 59, 112795) Тип: <class 'str'> Значение: 2024-12-20 21:37:59.112795 Репрезентация: '2024-12-20 21:37:59.112795'

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

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

    Так как они являются членами переменной, то сперва указывается ее имя, а уже потом через точку пишется название метода и скобки:

    someVariable = "Здесь притаилась какая-то строка." print(someVariable.__str__()) print(someVariable.__repr__())

    Такая запись выглядит некрасивой, нелаконичной и сложной. К тому же явное обращение к dunder-методам нельзя назвать хорошей практикой.

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

    import datetime dateNow = datetime.datetime.now() print("Значение (__str__()):", dateNow.__str__()) print("Репрезентация (__repr__()):", dateNow.__repr__()) print("") print("Значение (str()):", str(dateNow)) print("Репрезентация (repr()):", repr(dateNow))

    Консольный вывод этого примера будет таким:

    Значение (__str__()): 2024-12-20 21:53:03.167788 Репрезентация (__repr__()): datetime.datetime(2024, 12, 20, 21, 53, 3, 167788) Значение (str()): 2024-12-20 21:53:03.167788 Репрезентация (repr()): datetime.datetime(2024, 12, 20, 21, 53, 3, 167788)

    Как видно, результаты __str__() и str(), ровно как __repr__() и repr(), полностью совпадают.

    Переопределение str() и repr()

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

    При этом важно понимать, что в пользовательских классах Python автоматически не формирует возвращаемые значения этих методов:

    class Car: model = 'Tesla' version = 2 def __init__(self, model, version): self.model = model self.version = version someCar = Car("Cybertruck", 1) print(str(someCar)) # значение переменной print(repr(someCar)) # репрезентация переменной

    Консольный вывод этого примера будет таким:

    <__main__.Car object at 0x7acf8c5c5580> <__main__.Car object at 0x7acf8c5c5580>

    По умолчанию Python возвращает представление объекта во внутреннем формате. При этом, если в классе не определен метод __str__(), то вместо него вызывается __repr__().

    Поэтому хорошей практикой будет переопределение методов __str__() и __repr__() для каждого нового пользовательского класса:

    class Car: model = 'Tesla' version = 2 def __init__(self, model, version): self.model = model self.version = version def __str__(self): return str(self.model + " " + str(self.version) + ".0.0v") def __repr__(self): return "Car(" + repr(self.model) + ", " + str(self.version) + ")" someCar = Car("Cybertruck", 1) someOtherCar = eval(repr(someCar)) print(type(someCar)) print(type(someOtherCar)) print("") print(str(someCar)) print(repr(someCar)) print("") print(str(someOtherCar)) print(repr(someOtherCar))

    После запуска этого примера в консольном терминале появится вот такой вывод:

    <class '__main__.Car'> <class '__main__.Car'> Cybertruck 1.0.0v Car('Cybertruck', 1) Cybertruck 1.0.0v Car('Cybertruck', 1)

    Таким образом, благодаря переопределенным методам __str__() и __repr__() была создана точная копия оригинальной переменной пользовательского класса.**
    **


    Нужен сервер для практики? Арендуйте VPS/VDS в России — root-доступ, NVMe, DDoS-защита и поддержка 24/7.

    VPS для проекта

    VPS с root-доступом, NVMe и поддержкой 24/7 на Simple-Server.

    StarterVDS

    490₽

    в месяц

    1 ядро

    1 ГБ RAM

    20 ГБ NVMe

    • 1 IPv4
    • KVM
    • Root-доступ
    • Безлимитный трафик
    Заказать VPS
    Рекомендуем

    PerformanceVDS

    1190₽

    в месяц

    2 ядра

    4 ГБ RAM

    60 ГБ NVMe

    • 1 IPv4
    • KVM
    • Root-доступ
    • Базовая DDoS-защита
    Заказать VPS

    Нужна другая конфигурация или чистый VPS без панели?

    Все тарифы VPS

    Похожие статьи, которые могут быть вам интересны