На курсе я нашел следующий кусок кода:
class Ex(Exception):
def __init__(self, msg):
Exception.__init__(self, msg + msg)
self.args = (msg,)
try:
raise Ex('ex')
except Ex as e:
print(e)
except Exception as e:
print(e)
Прочитав это, я подумал, что печать e покажет exex, но это только ex.
Разве msg + msg не должны изменить его на exex?
Вы вручную устанавливаете .args
на self.args = (msg,)
Если вы удалите эту строку, она напечатает exex
Кажется, что super().__init__(msg + msg)
без возни с .args
лучше шаблон.
@juanpa.arrivillaga да, это было так. str задается args[0] (чего я не знал), и я не совсем понял, что следующая строка устанавливает args.
@MarkMeyer, это просто пример, сделанный, чтобы запутать ученика. Что явно подействовало на меня.
@motionsickness ну, нет, посмотрите на ответ, __str__
либо вернет пустую строку, если args
является пустым кортежем, либо первый элемент, если это кортеж длины один, либо просто строковый кортеж, если это множественный -элементный кортеж
BaseException.__str__
определяется здесь
static PyObject *
BaseException_str(PyBaseExceptionObject *self)
{
switch (PyTuple_GET_SIZE(self->args)) {
case 0:
return PyUnicode_FromString("");
case 1:
return PyObject_Str(PyTuple_GET_ITEM(self->args, 0));
default:
return PyObject_Str(self->args);
}
}
грубо переведено в псевдокод:
def __str__(self) -> str:
if len(self.args) == 0:
return ''
elif len(self.args) == 1:
return str(self.args[0])
else:
return str(self.args)
поэтому в этом случае, даже если вы инициализируете Exception.__init__
удвоением msg, вы сразу же забиваете self.args
исходным значением
если вы print(self.args)
до того, как назначите его, вы увидите свое двойное сообщение
если вы удалите задание self.args
, вы получите ожидаемое значение
@Chris, потому что строка 3 дважды объединяет сообщения.