Вопрос: Разница между __str__ и __repr__?


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


2060


источник


Ответы:


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

Во-первых, позвольте мне повторить основные моменты в Сообщение Alex :

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

Внедрение по умолчанию бесполезно

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

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

было бы слишком опасно (например, слишком легко попасть в бесконечную рекурсию, если объекты ссылаются друг на друга). Так что Питон уходит. Обратите внимание, что существует одно значение по умолчанию: 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)

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

Примечание: я использовал %rвыше, а не %s, Вы всегда хотите использовать repr()[или %rсимвол форматирования, эквивалентно] внутри __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__если вы считаете, что было бы полезно иметь строчную версию, которая ошибается на стороне большей читаемости в пользу большей двусмысленности.


2132



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


352



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

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


310



__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

139



Короче говоря, цель __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(); его   Цель состоит в том, чтобы вернуть печатную строку. Если аргумент не указан, возвращается   пустая строка, '',


110



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

__str__(читается как строка «dunder (double-underscore)») и __repr__(read as «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 ) что-то вроде:

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. Это создается датой __repr__:

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

Если мы печатаем объект datetime, мы видим хороший человеческий читаемый формат (по сути, ISO). Это выполняется с помощью datetime's __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=' ')

Задавать __repr__ = __str__?

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

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

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

Вывод

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


83



In all honesty, eval(repr(obj)) is never used. If you find yourself using it, you should stop, because eval is dangerous, and strings are a very inefficient way to serialize your objects (use pickle instead).

Therefore, I would recommend setting __repr__ = __str__. The reason is that str(list) calls repr on the elements (I consider this to be one of the biggest design flaws of Python that was not addressed by Python 3). An actual repr will probably not be very helpful as the output of print [your, objects].

To qualify this, in my experience, the most useful use case of the repr function is to put a string inside another string (using string formatting). This way, you don't have to worry about escaping quotes or anything. But note that there is no eval happening here.


10



On page 358 of the book Python scripting for computational science by Hans Petter Langtangen, it clearly states that

  • The __repr__ aims at a complete string representation of the object;
  • The __str__ is to return a nicely string for printing.

So, I prefer to understand them as

  • repr = reproduce
  • str = string (representation)

from the user point of view although this is a misunderstanding i made when learning python.

A small but good example is also given on the same page as follows:

Example

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'

10



Apart from all the answers given, I would like to add few points :-

1) __repr__() is invoked when you simply write object's name on interactive python console and press enter.

2) __str__() is invoked when you use object with print statement.

3) In case, if __str__ is missing, then print and any function using str() invokes __repr__() of object.

4) __str__() of containers, when invoked will execute __repr__() method of its contained elements.

5) str() called within __str__() could potentially recurse without a base case, and error on maximum recursion depth.

6) __repr__() can call repr() which will attempt to avoid infinite recursion automatically, replacing an already represented object with ....


10