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

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

21 ответов


Алекс резюмировал хорошо, но, как ни странно, был слишком лаконичен.

во-первых, позвольте мне подчеркнуть основные моменты в Алекс:

  • реализация по умолчанию бесполезна (трудно придумать тот, который не был бы, Но да)
  • __repr__ цель должна быть однозначной
  • __str__ цель должна быть читаемой
  • контейнера!--5--> использует объекты’ __repr__

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

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

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

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

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

цель __repr__ должен быть однозначным

позвольте мне выйти прямо и сказать это - я не верьте в отладчики. Я действительно не знаю, как использовать любой отладчик, и никогда не использовал его серьезно. Кроме того, я считаю, что большая ошибка в отладчиках - это их основная природа-большинство сбоев, которые я отлаживаю, произошли очень давно, в далекой галактике. Это значит, что я с религиозным рвением верю в лесозаготовки. Ведение журнала-это жизненная сила любой приличной серверной системы fire-and-forget. 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, то ее str выглядит как 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__ если вы считаете, что было бы полезно иметь строковую версию, которая ошибается на стороне большей читаемости в пользу большей двусмысленности.


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


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

>>> 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__!


__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

короче говоря, цель __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:

repr(object)

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

здесь документация по str:

str(object='')

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


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

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

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

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

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

__str__

если вы печатаете объект или передать его в format, str.format или str, то если a __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__ is (C Источник Python) что-то типа:

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 = ", ".join(map(str, L))
    s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s)
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    return s

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

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

Set __repr__ = __str__?

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

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

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

вывод

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


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

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

2) __str__() вызывается при использовании object с инструкцией print.

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

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

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

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


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

  • на __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'

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

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

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


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

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

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


от http://pyref.infogami.com/__str__ по effbot:

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


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

  • цель __str__: удобочитаемое
  • цель __repr__: однозначный, возможно машиночитаемый через eval

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


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

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

отличия:

str ():

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

repr ():

  • нужен код, который воспроизводит объект
  • производит выход для разработчик

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

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

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))

>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

когда print () вызывается в результате decimal.Decimal (23) / deci - mal.Decimal ("1.05") печатается сырое число; этот вывод находится в строку чего можно достигнуть с _ _ str __(). Если мы просто введем выражение, мы получим десятичное число.Decimal output-этот выход находится в изобразительная форма чего можно достигнуть с _ _ repr __(). Все объекты Python имеют две формы вывода. Строковая форма предназначена для чтения человеком. Репрезентативная форма предназначен для получения вывода, который при подаче интерпретатору Python будет (когда это возможно) повторно производить представленный объект


одна важная вещь, котор нужно держать в разуме что контейнер __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 предпочитает однозначность читаемости, the __str__ вызов tuple называет объекты' __repr__ на "формальной" представление объекта. Хотя формальное представление труднее читать, чем неформальное, оно однозначное и более надежное против ошибок.


"A basic requirement for a Python object is to provide usable 
 string   representations of itself, one used for debugging and
 logging, another for presentation to end users. That is why the  
 special methods __repr__ and __str__ exist in the data model."

из книги: свободно Python


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

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'

понять __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

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


Так гораздо яснее от блог

str похоже на toString. создано для печати данных repr похоже на сериализацию или рассол. Как я ... --10-->заново этот объект, если мне нужно сделать это с помощью 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))

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