Почему Python `кроме` не использует `isinstance`? - PullRequest
8 голосов
/ 02 октября 2010

Документация Python для except гласит:

Для исключающей оговорки с выражение, это выражение оценивается, и предложение соответствует исключение, если результирующий объект «Совместимый» с исключением. объект совместим с исключением если это класс или базовый класс объекта исключения , [...]

Почему except не использует isinstance вместо сравнения базовых классов? Это предотвращает использование __instancecheck__ для переопределения проверки экземпляра.

EDIT:

Я могу понять, что одной из причин, по которой этого не существует, является то, что никто не учел это. Но есть ли причины, по которым это не должно быть реализовано?

EDIT:

Сеанс оболочки из Python 3.2a, показывающий, что попытка использовать __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 ]

3 голосов
/ 02 октября 2010

Простой ответ, вероятно, состоит в том, что никто не учел это.Более сложным ответом было бы то, что никто не подумал об этом, потому что это трудно понять правильно, потому что это означало бы выполнение потенциально произвольного кода Python при обработке исключения , и что оно имеет сомнительную ценность.Классы исключений в Python, как правило, являются очень простыми классами, и перегрузка их функциональностью часто является ошибкой.Трудно представить себе случай, когда он проконсультировался __instancecheck__.Если у вас есть такой случай (с патчем или без него), сообщите об ошибке, и кто-то может ее исправить.

1 голос
/ 02 октября 2010

Но есть ли причины, по которым это не должно быть реализовано?

Можете ли вы привести пример, где это было бы полезно?

Когда вы делаете это:

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__ в метаклассе SomeType, чтобы определить, является ли Something подклассом SomeType. Метакласс PEP говорит об этом более подробно.

...