Разница между __str__ и __repr__?

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

2396
17 сент. '09 в 7:27
источник поделиться
23 ответов

Алекс подвела итог, но, на удивление, была слишком лаконична.

Во-первых, позвольте мне повторить основные моменты в посте Алекса:

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

Реализация по умолчанию бесполезна

Это в основном сюрприз, потому что значения Python по умолчанию довольно полезны. Тем не менее, в этом случае наличие по умолчанию для __repr__ которое будет действовать следующим образом:

return "%s(%r)" % (self.__class__, self.__dict__)

было бы слишком опасно (например, слишком легко попасть в бесконечную рекурсию, если объекты ссылаются друг на друга). Так что Python справляется. Обратите внимание, что существует одно значение по умолчанию: true, если __repr__ определен, а __str__ нет, объект будет вести себя так, как если бы __str__=__repr__.

Проще говоря, это означает, что почти каждый реализуемый вами объект должен иметь функционал __repr__ можно использовать для понимания объекта. Реализация __str__ необязательна: делайте это, если вам нужна функциональность "симпатичная печать" (например, используемая генератором отчетов).

Цель __repr__ - быть однозначным

Позвольте мне выйти и сказать это - я не верю в отладчики. Я действительно не знаю, как использовать любой отладчик, и никогда не использовал его серьезно. Кроме того, я считаю, что большая ошибка отладчиков заключается в их основной природе - большинство ошибок, которые я отлаживал, произошли очень давно, в галактике очень далеко. Это означает, что я с религиозным рвением верю в заготовку леса. Ведение журналов - жизненная основа любой достойной серверной системы, работающей по принципу "забей и забудь". Python облегчает вход в систему: возможно, с некоторыми обертками, специфичными для проекта, все, что вам нужно, это

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

Но вы должны сделать последний шаг - убедиться, что у каждого объекта, который вы реализуете, есть полезный repr, чтобы подобный код мог просто работать. Вот почему возникает "eval": если у вас достаточно информации, eval(repr(c))==c, это означает, что вы знаете все, что нужно знать о c. Если это достаточно просто, по крайней мере, нечетко, сделайте это. Если нет, убедитесь, что у вас достаточно информации о c. Я обычно использую eval-подобный формат: "MyClass(this=%r,that=%r)" % (self.this,self.that). Это не означает, что вы на самом деле можете создать MyClass или что это правильные аргументы конструктора - но это полезная форма для выражения "это все, что вам нужно знать об этом экземпляре".

Примечание: я использовал %r выше, а не %s. Вы всегда хотите использовать repr() [или символ форматирования %r, эквивалентно] внутри реализации __repr__, или вы побеждаете цель repr. Вы хотите иметь возможность различать MyClass(3) и MyClass("3").

Цель __str__ - быть читабельным

В частности, оно не должно быть однозначным - обратите внимание, что str(3)==str("3"). Точно так же, если вы реализуете абстракцию IP, иметь такую строку, как 192.168.1.1, просто прекрасно. При реализации абстракции даты/времени str может быть "2010/4/12 15:35:22" и т.д. Цель состоит в том, чтобы представить ее так, чтобы ее захотел прочитать пользователь, а не программист. Отрежьте ненужные цифры, притворитесь каким-то другим классом - пока он поддерживает читабельность, это улучшение.

Контейнеры __str__ использует содержащиеся объекты __repr__

Это кажется удивительным, не так ли? Это немного, но насколько бы читабельным было бы

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

быть? Не очень. В частности, строки в контейнере слишком легко нарушить его представление строки. Помните, что перед лицом двусмысленности Python сопротивляется искушению угадать. Если вам нужно описанное выше поведение при печати списка, просто

print "[" + ", ".join(l) + "]"

(Вы также можете выяснить, что делать со словарями.

Резюме

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

2455
13 апр. '10 в 3:56
источник

Мое правило: __repr__ для разработчиков, __str__ для клиентов.

443
17 сент. '09 в 14:35
источник

Если вы специально не обязываетесь в противном случае, большинство классов не имеют полезных результатов для:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 

Как вы видите - никакой разницы и никакой информации, кроме класса и объекта id. Если вы только переопределите один из двух...:

>>> class Sic(object): 
...   def __repr__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
...   def __str__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
<__main__.Sic object at 0x2617f0>
>>> 

как вы видите, если вы переопределите __repr__, который ТАКЖЕ используется для __str__, но не наоборот.

Другие важные моменты: __str__ на встроенном контейнере использует __repr__, а не __str__ для элементов, которые он содержит. И, несмотря на слова по этому вопросу, найденные в типичных документах, вряд ли кто-нибудь беспокоится о том, что __repr__ объектов будет строкой, которую eval может использовать для создания равного объекта (это слишком сложно, И не зная, как соответствующий модуль был фактически импортирован, делает его фактически плоским невозможным).

Итак, мой совет: сосредоточьтесь на том, чтобы сделать __str__ разумно понятным для человека и __repr__ настолько однозначным, насколько возможно, даже если это мешает нечеткой недостижимой цели сделать возвращаемое значение __repr__ приемлемым в качестве входного __eval__!

359
17 сент. '09 в 7:49
источник

__repr__: представление объекта python обычно eval будет преобразовывать его обратно в этот объект

__str__: это то, что вы думаете, это объект в текстовой форме

например.

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True
154
17 сент. '09 в 7:35
источник

Короче говоря, цель __repr__ - быть однозначной, а __str__ - читаемым.

Вот хороший пример:

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'

Прочтите эту документацию для версии:

repr(object)

Возвращает строку, содержащую печатаемое представление объекта. Это то же значение, которое дает конверсия (обратная кавычки). Иногда полезно иметь доступ к этой операции как обычная функция. Для многих типов эта функция делает попытку для возврата строки, которая даст объект с тем же значением, когда передан в eval(), иначе представление представляет собой строку, заключенную в угловые скобки, содержащие имя типа объекта вместе с дополнительной информацией, часто включающей название и адрес объекта. Класс может управлять тем, что возвращает эта функция для его экземпляров, определяя метод __repr__().

Вот документация для str:

str(object='')

Возвращает строку, содержащую красиво представление объекта. Для строк это возвращает строку сам. Разница с repr(object) заключается в том, что str(object) не всегда пытайтесь вернуть строку, приемлемую для eval(); его Цель состоит в том, чтобы вернуть печатную строку. Если аргумент не указан, возвращается пустая строка, ''.

131
25 окт. '13 в 21:38
источник

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

__str__ (читается как "dunder (двойное подчеркивание) строка") и __repr__ (читается как "dunder-repper" (для "представления")) оба являются специальными методами, которые возвращают строки в зависимости от состояния объекта.

__repr__ обеспечивает резервное копирование, если __str__ отсутствует.

Поэтому сначала нужно написать __repr__ который позволяет вам восстановить экземпляр эквивалентного объекта из строки, которую он возвращает, например, используя eval или набирая его символ за символом в оболочке Python.

В любое время позже можно написать __str__ для читаемого пользователем строкового представления экземпляра, когда он считает это необходимым.

__str__

Если вы печатаете объект или передаете его в format, str.format или str, то если определен метод __str__, будет вызван этот метод, в противном случае будет использоваться __repr__.

__repr__

Метод __repr__ вызывается встроенной функцией repr и является тем, что отображается в вашей оболочке python, когда он вычисляет выражение, возвращающее объект.

Поскольку он предоставляет резервную копию для __str__, если вы можете написать только одну, начните с __repr__

Вот встроенная справка по repr:

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

То есть, для большинства объектов, если вы напечатаете то, что напечатано с помощью repr, вы сможете создать эквивалентный объект. Но это не реализация по умолчанию.

Реализация по умолчанию __repr__

Объект по умолчанию __repr__ (источник на C Python) __repr__ примерно так:

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

Это означает, что по умолчанию вы будете печатать модуль, из которого объект, имя класса и шестнадцатеричное представление его расположения в памяти - например:

<__main__.Foo object at 0x7f80665abdd0>

Эта информация не очень полезна, но нет способа определить, как можно точно создать каноническое представление любого конкретного экземпляра, и это лучше, чем ничего, по крайней мере, сказать нам, как мы могли бы уникально идентифицировать ее в памяти.

Чем может быть полезен __repr__?

Давайте посмотрим, насколько это может быть полезно, используя оболочку Python и объекты datetime. Сначала нам нужно импортировать модуль datetime:

import datetime

Если мы вызовем datetime.now в оболочке, мы увидим все, что нам нужно для воссоздания эквивалентного объекта datetime. Это создается datetime __repr__:

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

Если мы печатаем объект datetime, мы видим хороший читабельный (на самом деле, ISO) формат. Это реализовано datetime __str__:

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

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

>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180

Как мне их реализовать?

По мере разработки вы захотите иметь возможность воспроизводить объекты в том же состоянии, если это возможно. Так, например, объект datetime определяет __repr__ (источник Python). Это довольно сложно из-за всех атрибутов, необходимых для воспроизведения такого объекта:

def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day,  # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = "%s.%s(%s)" % (self.__class__.__module__,
                       self.__class__.__qualname__,
                       ", ".join(map(str, L)))
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    if self._fold:
        assert s[-1:] == ")"
        s = s[:-1] + ", fold=1)"
    return s

Если вы хотите, чтобы ваш объект имел более удобочитаемое представление, вы можете использовать __str__ next. Вот как объект datetime (источник Python) реализует __str__, что он легко делает, потому что у него уже есть функция для отображения в формате ISO:

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

Установить __repr__ = __str__?

Это критика другого ответа, который предлагает установить __repr__ = __str__.

Установка __repr__ = __str__ глупа - __repr__ является __repr__ для __str__ а __repr__, написанный для разработчиков при отладке, должен быть написан до того, как вы напишите __str__.

__str__ вам нужен только тогда, когда вам нужно текстовое представление объекта.

Заключение

Определите __repr__ для объектов, которые вы пишете, чтобы вы и другие разработчики имели воспроизводимый пример при использовании его по мере разработки. Определите __str__ когда вам нужно его читаемое строковое представление.

97
25 янв. '15 в 5:01
источник

Помимо всех ответов, я хотел бы добавить несколько моментов:

1) __repr__() вызывается, когда вы просто пишете имя объекта на интерактивной консоли python и нажимаете ввод.

2) __str__() вызывается, когда вы используете объект с оператором печати.

3) В случае если __str__ отсутствует, то print и любая функция, использующая str() вызывает __repr__() объекта.

4) __str__() контейнеров, при вызове выполнит __repr__() его содержащихся элементов.

5) str() вызываемая в __str__() потенциально может рекурсировать без базового случая и ошибки при максимальной глубине рекурсии.

6) __repr__() может вызвать repr() который попытается автоматически избежать бесконечной рекурсии, заменив уже представленный объект на ...

25
08 сент. '16 в 6:27
источник

На странице 358 книги скриптов Python для вычислительной науки Ханса Петтера Лангтангена ясно сказано, что

  • __repr__ нацелен на полное строковое представление объекта;
  • __str__ должен возвращать красивую строку для печати. ​​

Итак, я предпочитаю понимать их как

  • repr = воспроизведение
  • str = строка (представление)

с точки зрения пользователя хотя это недоразумение, которое я сделал при изучении python.

Небольшой, но хороший пример также приведен на одной странице следующим образом:

Пример

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'
17
21 мая '17 в 19:34
источник

Проще говоря:

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

__repr__ используется для отображения строкового представления объекта .

Предположим, что я хочу создать класс Fraction, где строковое представление фракции равно "(1/2)", а объект (класс фракции) должен быть представлен как "Фракция (1,2)"

Итак, мы можем создать простой класс фракции:

class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)
11
12 янв. '16 в 5:53
источник

Всем честно, eval(repr(obj)) никогда не используется. Если вы его используете, вы должны остановиться, потому что eval является опасным, а строки - очень неэффективным способом сериализации ваших объектов (вместо этого используйте pickle).

Поэтому я бы рекомендовал установить __repr__ = __str__. Причина в том, что str(list) вызывает repr для элементов (я считаю, что это один из самых больших недостатков дизайна Python, который не рассматривался Python 3). Фактический repr, вероятно, не будет очень полезен для вывода print [your, objects].

Чтобы квалифицировать это, по моему опыту, наиболее полезным вариантом использования функции repr является поместить строку внутри другой строки (используя форматирование строк). Таким образом, вам не нужно беспокоиться об ускорении кавычек или чего-то еще. Но обратите внимание, что здесь нет eval.

11
15 нояб. '12 в 13:39
источник

Из (неофициальной) справочной вики Python (архивная копия) от effbot:

__str__ "вычисляет" неформальное "строковое представление объекта. Это отличается от __repr__ в том, что оно не обязательно должно быть допустимым выражением Python: вместо него можно использовать более удобное или сжатое представление."

10
17 сент. '09 в 7:28
источник

Один аспект, отсутствующий в других ответах. Это правда, что в общем случае шаблон выглядит следующим образом:

  • Цель __str__: доступная для человека
  • Цель __repr__: однозначная, возможно машиночитаемая через eval

К сожалению, эта дифференциация ошибочна, потому что Python REPL, а также IPython используют __repr__ для печати объектов в консоли REPL (см. связанные вопросы для Python и IPython). Таким образом, проекты, предназначенные для интерактивной работы в консоли (например, Numpy или Pandas), начали игнорировать вышеприведенные правила и вместо этого представлять собой понятную для человека реализацию __repr__.

7
26 мая '17 в 15:33
источник

str - Создает новый строковый объект из данного объекта.

repr - Возвращает каноническое строковое представление объекта.

Различия:

ул():

  • делает объект доступным для чтения
  • генерирует выходные данные для конечного пользователя

магнезии():

  • требуется код, который воспроизводит объект
  • генерирует выходные данные для разработчика
6
04 дек. '16 в 19:18
источник

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

По этой причине, если у меня достаточно простой __str__, я обычно пытаюсь получить лучшее из обоих миров с чем-то вроде:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))
4
29 окт. '15 в 20:46
источник

Из книги Свободный Питон:

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

4
04 апр. '17 в 15:35
источник

В двух словах:

class Demo:
  def __repr__(self):
    return 'repr'
  def __str__(self):
    return 'str'

demo = Demo()
print(demo) # use __str__, output 'str' to stdout

s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'

import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout

from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'
3
23 марта '18 в 13:30
источник

Чем яснее из блог

str похож на toString., чтобы вы могли распечатать данные repr похож на сериализацию или рассол. Как мне воссоздать этот объект, если мне нужно это сделать, используя eval()

>>> import datetime
>>> now = datetime.datetime.now() 
>>> str(now)
'2015-04-04 20:51:31.766862'
>>> repr(now)
'datetime.datetime(2015, 4, 4, 20, 51, 31, 766862)'
>>mydate = eval(repr(now))
3
01 апр. '18 в 16:32
источник

Важно помнить, что контейнер __str__ использует содержащиеся объекты __repr__.

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

Python поддерживает однозначность над читабельностью, вызов __str__ tuple вызывает содержащиеся в нем объекты __repr__, "формальное" представление объекта. Хотя формальное представление труднее читать, чем неофициальное, оно однозначно и более устойчиво к ошибкам.

3
16 нояб. '15 в 6:02
источник
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

Когда print() вызывается по результату decimal.Decimal(23)/decimal.Decimal("1.05") печатается необработанное число; это вывод в виде строки, который может быть достигнут с __str__(). Если мы просто введем выражение, мы получим decimal.Decimal вывод. decimal.Decimal вывод - этот вывод представлен в форме представления, которая может быть достигнута с помощью __repr__(). Все объекты Python имеют две выходные формы. Строковая форма разработана для восприятия человеком. Представительная форма предназначена для создания выходных данных, которые при передаче интерпретатору Python (когда это возможно) воспроизводят представленный объект.

3
15 июля '15 в 13:30
источник

Понимать __str__ и __repr__ интуитивно и постоянно различать их вообще.

__str__ возвращает строку замаскированного тела данного объекта для чтения глаз

__repr__ вернуть реальное тело тела данного объекта (вернуть себя) для однозначности, чтобы идентифицировать.

См. это в примере

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

Что касается __repr__

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

Мы можем легко выполнить арифметическую операцию на __repr__.

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

если применить операцию на __str__

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Возвращает только ошибку.

Другой пример.

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

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

2
07 дек. '17 в 11:03
источник

__repr__ используется везде, кроме методов print и str (когда определен __str__ !)

1
08 мая '18 в 11:49
источник

__str__ может быть вызван для объекта путем вызова str(obj) и должен вернуть читаемую человеком строку.

__repr__ может быть вызван для объекта путем вызова repr(obj) или с помощью обратных галочек obj и должен возвращать внутренний объект (поля/атрибуты объекта)

Этот пример может помочь:

class C1:pass

class C2:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

class C3:        
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")

class C4:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")


ci1 = C1()    
ci2 = C2()  
ci3 = C3()  
ci4 = C4()

print(ci1)       #<__main__.C1 object at 0x0000024C44A80C18>
print(str(ci1))  #<__main__.C1 object at 0x0000024C44A80C18>
print(repr(ci1)) #<__main__.C1 object at 0x0000024C44A80C18>
print(ci2)       #C2 class str
print(str(ci2))  #C2 class str
print(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>
print(ci3)       #C3 class repr
print(str(ci3))  #C3 class repr
print(repr(ci3)) #C3 class repr
print(ci4)       #C4 class str 
print(str(ci4))  #C4 class str 
print(repr(ci4)) #C4 class repr
0
06 июня '19 в 19:53
источник
  1. __str__ должен возвращать строковый объект, тогда как __repr__ может возвращать любое выражение python.
  2. Если реализация __str__ отсутствует, то функция __repr__ используется как запасной вариант. Нет __repr__ если __repr__ реализация функции __repr__.
  3. Если функция __repr__ возвращает __repr__ представление объекта, мы можем пропустить реализацию функции __str__.

Источник: https://www.journaldev.com/22460/python-str-repr-functions

0
18 апр. '19 в 14:20
источник

Посмотрите другие вопросы по меткам или Задайте вопрос