我一直在寻找一些对某些人来说可能相对愚蠢的东西,但对我来说非常有趣! :-)
输入和输出错误已合并为OSError
在 Python 3.3 中,异常类层次结构发生了变化。关于内置类的一个有趣的特性OSError
是这样,它在传递时返回它的子类errno
and strerror
>>> OSError(2, os.strerror(2))
FileNotFoundError(2, 'No such file or directory')
>>> OSError(2, os.strerror(2)).errno
2
>>> OSError(2, os.strerror(2)).strerror
'No such file or directory'
正如你所看到的经过errno
and strerror
到构造函数OSError
回报FileNotFoundError
实例是 的子类OSError
.
Python 文档:
构造函数通常实际上返回 OSError 的子类,如 OS 中所述例外情况 https://docs.python.org/3/library/exceptions.html#os-exceptions以下。特定的子类取决于最终的 errno 值。此行为仅在直接或通过别名构造 OSError 时发生,并且在子类化时不会继承。
我想编写一个以这种方式运行的子类。这主要是出于好奇,而不是现实世界的代码。我也想知道,创建子类对象的逻辑在哪里,它是用什么编码的__new__
例如?如果__new__
包含创建子类实例,然后继承的逻辑OSError
通常会返回此行为,除非存在某种类型检查__new__
:
>>> class A(OSError): pass
>>> A(2, os.strerror(2))
A(2, 'No such file or directory')
那么必须进行类型检查:
# If passed OSError, returns subclass instance
>>> A.__new__(OSError, 2, os.strerror(2))
FileNotFoundError(2, 'No such file or directory')
# Not OSError? Return instance of A
>>> A.__new__(A, 2, os.strerror(2)
A(2, 'No such file or directory')
我一直在深入研究 C 代码,以找出该代码的确切位置,并且由于我不是 C 方面的专家,我怀疑这确实是逻辑(坦率地说,我对此非常怀疑):
异常.c https://hg.python.org/cpython/file/5ae8756a1ae0/Objects/exceptions.c
if (myerrno && PyLong_Check(myerrno) &&
errnomap && (PyObject *) type == PyExc_OSError) {
PyObject *newtype;
newtype = PyDict_GetItem(errnomap, myerrno);
if (newtype) {
assert(PyType_Check(newtype));
type = (PyTypeObject *) newtype;
}
else if (PyErr_Occurred())
goto error;
}
}
现在我想知道扩展的可能性errnomap
来自Python本身而不使用C代码,所以OSErro
可以创建用户定义类的实例,如果你问我为什么要这样做?我想说,只是为了好玩。