Просто поставьте супер init (config) в первой строке вашего переопределенного метода
public void init(ServletConfig config) throws ServletException
Алекс резюмировал хорошо, но, к удивлению, был слишком лаконичным.
Во-первых, позвольте мне повторить основные моменты из сообщения Алекса :
__ 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 __
, если вы считаете, что было бы полезно иметь строковую версию, которая допускает ошибки для удобочитаемости.
__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
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__
!
Мое практическое правило: __ repr __
для разработчиков, __ str __
для клиентов.
Из (неофициальной) справочной вики-страницы Python (архивная копия) от effbot:
__ str __
" вычисляет "неформальное" строковое представление объекта. Оно отличается от __ repr __
тем, что не обязательно должно быть допустимым выражением Python: вместо него может использоваться более удобное или краткое представление. "