Разница между __str__ и __repr__?

Просто поставьте супер init (config) в первой строке вашего переопределенного метода

public void init(ServletConfig config) throws ServletException
2471
задан Georgy 29 May 2019 в 10:56
поделиться

5 ответов

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

Во-первых, позвольте мне повторить основные моменты из сообщения Алекса :

  • Реализация по умолчанию бесполезна (трудно придумать такую, которая бы не была, но да)
  • __ repr __ цель - быть недвусмысленной
  • __ str __ цель - быть читаемой
  • Контейнер __ str __ использует содержащиеся объекты ' __ repr __

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

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

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

, было бы слишком опасно (например, слишком легко попасть в бесконечную рекурсию, если объекты ссылаются друг на друга). Итак, Python уходит. Обратите внимание, что есть одно значение по умолчанию, которое истинно: если __ 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 . Я обычно использую формат, похожий на 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 - это нормально. При реализации абстракции даты / времени строка может иметь вид «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 __ , если вы считаете, что было бы полезно иметь строковую версию, которая допускает ошибки для удобочитаемости.

2583
ответ дан 22 November 2019 в 19:51
поделиться

__repr__: representation of python object usually eval will convert it back to that object

__str__: is whatever you think is that object in text form

e.g.

>>> 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
159
ответ дан 22 November 2019 в 19:51
поделиться

Unless you specifically act to ensure otherwise, most classes don't have helpful results for either:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 

As you see -- no difference, and no info beyond the class and object's id. If you only override one of the two...:

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

as you see, if you override __repr__, that's ALSO used for __str__, but not vice versa.

Other crucial tidbits to know: __str__ on a built-on container uses the __repr__, NOT the __str__, for the items it contains. And, despite the words on the subject found in typical docs, hardly anybody bothers making the __repr__ of objects be a string that eval may use to build an equal object (it's just too hard, AND not knowing how the relevant module was actually imported makes it actually flat out impossible).

So, my advice: focus on making __str__ reasonably human-readable, and __repr__ as unambiguous as you possibly can, even if that interferes with the fuzzy unattainable goal of making __repr__'s returned value acceptable as input to __eval__!

380
ответ дан 22 November 2019 в 19:51
поделиться

Мое практическое правило: __ repr __ для разработчиков, __ str __ для клиентов.

479
ответ дан 22 November 2019 в 19:51
поделиться

Из (неофициальной) справочной вики-страницы Python (архивная копия) от effbot:

__ str __ " вычисляет "неформальное" строковое представление объекта. Оно отличается от __ repr __ тем, что не обязательно должно быть допустимым выражением Python: вместо него может использоваться более удобное или краткое представление. "

10
ответ дан 22 November 2019 в 19:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: