为什么Python的`except`不使用`isinstance`?
关于 except
的用法,Python 文档中提到:
在有表达式的
except
子句中,这个表达式会被计算,如果计算出的结果与异常相匹配,就会执行这个子句。一个对象与异常相匹配的条件是它是异常对象的类或其父类,[...]
那么,为什么 except
不用 isinstance
来判断,而是通过比较父类呢?这样做就不能使用 __instancecheck__
来重写实例检查。
补充:
我能理解为什么没有人考虑过这个问题,但有没有什么理由说明这不应该被实现呢?
补充:
下面是一个来自 Python 3.2a 的 shell 会话,显示尝试使用 __subclasscheck__
来实现这个功能是行不通的:
>>> class MyType(type): __subclasscheck__ = lambda cls, other_cls: True
>>> class O(Exception, metaclass=MyType): pass
>>> issubclass(3, O)
0: True
>>> issubclass(int, O)
1: True
>>> try:
... 1/0
... except O:
... print('Success')
Traceback (most recent call last):
File "<pyshell#4>", line 2, in <module>
1/0
ZeroDivisionError: division by zero
>>>
2 个回答
2
但是,有没有什么理由说明这不应该被实现呢?
你能举个例子说明这有什么用吗?
当你这样做的时候:
class SomeMeta(type):
def __subclasscheck__(cls, sub):
print (cls, sub)
return True
class Something(Exception):
pass
class SomeType(Exception):
__metaclass__ = SomeMeta
try:
raise Something()
except SomeType, e:
pass
# prints (<class '__main__.SomeType'>, <class '__main__.Something'>)
Python会调用__subclasscheck__
这个方法,来检查Something
是否是SomeType
的子类。关于这个,元类PEP有更详细的说明。
5
简单来说,可能是因为没人考虑过这个问题。更复杂的说法是,没人考虑过是因为这很难做到,因为这意味着在处理异常的时候要执行可能是任意的Python代码,而这其实价值不大。在Python中,异常类通常都是非常简单的类,给它们添加太多功能往往是个错误。很难想象有什么情况需要去调用 __instancecheck__
。如果你真的有这样的情况(无论有没有补丁),可以提交一个bug,可能会有人关注这个问题。