为什么我会在以下两个代码段(Python 3.4)中获得不同的结果:
class MainError(Exception):
def __init__(self, msg, **parms):
super().__init__()
self.msg = msg
self.parms = parms
print('Parms original', parms)
def __str__(self):
return self.msg + ':' + str(self.parms)
class SubError(MainError):
def __init__(self, msg, **parms):
super().__init__(msg, **parms)
try:
raise SubError('Error occured', line = 22, col = 11)
except MainError as e:
print(e)
>>>
Parms original {'line': 22, 'col': 11}
Error occured:{'line': 22, 'col': 11}
和
class MainError(Exception):
def __init__(self, msg, **args):
super().__init__()
self.msg = msg
self.args = args
print('Parms original', args)
def __str__(self):
return self.msg + ':' + str(self.args)
class SubError(MainError):
def __init__(self, msg, **args):
super().__init__(msg, **args)
try:
raise SubError('Error occured', line = 22, col = 11)
except MainError as e:
print(e)
>>>
Parms original {'line': 22, 'col': 11}
Error occured:('line', 'col')
答案 0 :(得分:2)
这是因为错误args被覆盖,通过将它们转换为C级别的Python元组。
这是Python的BaseException类: https://hg.python.org/cpython/file/tip/Objects/exceptions.c
从第31行开始,我们看到以下内容:
static PyObject *
BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyBaseExceptionObject *self;
self = (PyBaseExceptionObject *)type->tp_alloc(type, 0);
if (!self)
return NULL;
/* the dict is created on the fly in PyObject_GenericSetAttr */
self->dict = NULL;
self->traceback = self->cause = self->context = NULL;
self->suppress_context = 0;
if (args) {
self->args = args;
Py_INCREF(args);
return (PyObject *)self;
}
self->args = PyTuple_New(0);
if (!self->args) {
Py_DECREF(self);
return NULL;
}
return (PyObject *)self;
}
同样,init调用具有相同的元组转换:
BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds)
{
PyObject *tmp;
if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
return -1;
tmp = self->args;
self->args = args;
Py_INCREF(self->args);
Py_XDECREF(tmp);
return 0;
}
简而言之,self.args正在转换为元组,并将其转换回字符串,从而产生差异。
为所有方法包装器调用BaseException类(我相信)作为必需参数。
如果传递一个不可迭代的参数(例如整数),这是很明显的:
>>> class CustomException(Exception):
... def __init__(self):
... super(CustomException, self).__init__('a')
... self.args = 1
... def __repr__(self):
... print(self.args)
... return ''
...
>>> CustomException()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
TypeError: 'int' object is not iterable
故事的道德:不要将您的变量命名为经常重新定义的词,并且是您正在使用的课程的关键术语。