Разница между str и repr?
в чем разница между __str__
и __repr__
in Python
?
21 ответ:
Алекс хорошо описаны, но, на удивление, был слишком лаконичен.
во-первых, позвольте мне подчеркнуть основные моменты в Алекс:
- реализация по умолчанию бесполезна (трудно придумать тот, который не был бы, Но да)
__repr__
цель должна быть однозначной- контейнера!--5--> использует объекты’
__str__
цель состоит в том, чтобы быть читаемым__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__
если вы считаете, что было бы полезно иметь строковую версию, которая ошибается на стороне большей читаемости в пользу большей двусмысленности.
если вы специально не действуете, чтобы гарантировать обратное, большинство классов не имеют полезных результатов ни для того, ни для другого:
>>> 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__
вызов atuple
называет объекты'__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))