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


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

21 2176

21 ответ:

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

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

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

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

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

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

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

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

цель __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, то наличие 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]

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

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__'s возвращаемое значение приемлемо в качестве входных данных для __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)

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

здесь документации: ул.

str(object='')

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

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

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

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

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

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

__str__

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

__repr__

The __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 source) что-то типа:

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 source). Это довольно сложно, потому что все атрибуты, необходимые для воспроизведения такого объекта:

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 source) реализует __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__() вызывается при использовании объекта с оператором print.

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

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

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

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

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

  • The __repr__ стремится к полному строковому представлению объекта;
  • The __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__ используется для отображения строкового представления the

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

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

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

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

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

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

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.Десятичное число ("1.05") необработанное число печатается; этот вывод находится в строку что может быть достигнуто с _ _ str __(). Если мы просто введем выражение, мы получим десятичное число.Десятичный вывод-этот вывод находится в изобразительная форма что может быть достигнуто с _ _ 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 предпочитает однозначность над удобочитаемостью на __str__ вызов a 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."

из книги: Fluent 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 это как сериализация, или рассол. Как же я заново этот объект, если мне нужно сделать это с помощью 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 когда a __str__определен