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