为什么Python的`except`不使用`isinstance`?

9 投票
2 回答
2648 浏览
提问于 2025-04-16 04:52

关于 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,可能会有人关注这个问题。

撰写回答