args
被实现为一个数据描述符__get__
and __set__
方法。
这发生在内部BaseException.__new__
就像@bakatrouble提到的那样。除此之外,里面发生了什么BaseException.__new__
大致类似于下面的Python代码:
class BaseException:
def __new__(cls, *args):
# self = create object of type cls
self.args = args # This calls: BaseException.args.__set__(self, args)
...
return self
在C代码中Python 3.7.0 阿尔法 1,上面的Python代码看起来像这样(检查 Python 的 C 代码是否有任何过去或未来的差异):
BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
# other things omitted...
self = (PyBaseExceptionObject *)type->tp_alloc(type, 0);
# many things follow...
if (args) {
self->args = args;
Py_INCREF(args);
return (PyObject *)self;
}
# many more things follow
}
交互实验:
>>> e = Exception('aaa')
>>> e
Exception('aaa',)
>>> BaseException.args.__set__(e, ('bbb',))
>>> e
Exception('bbb',)
>>> BaseException.args.__get__(e)
('bbb',)
因此,神奇的灵感args
让你的眼睛望向天堂的事情发生在BaseException.__new__
,当一个对象BaseException
或其任何子类被创建。