`попробуй ... кроме не` конструкции - PullRequest
7 голосов
/ 10 мая 2019

Недавно я встретил пример кода, который никогда раньше не видел:

try:
    # a simple bunch of code
    if sample == 0:
        return True
    else:
        raise ExampleError()
except not ExampleError:
    raise AnotherExampleError()

Как это работает (если вообще работает)?

Ответы [ 3 ]

8 голосов
/ 10 мая 2019

РЕДАКТИРОВАТЬ: Ответ ниже был для Python 3, я не понял вопрос, связанный с Python 2.7.в Python 2, как кажется, интерпретатор не жалуется, если выражение после except не приводит к подтипу BaseException.Тем не менее, поведение по-прежнему неправильное, оно просто игнорирует этот блок except во всех случаях.


Это забавная конструкция, синтаксически допустимая, но семантически неверная.Я предполагаю, что автор кода хотел выразить что-то вроде «запустить этот блок except для любого типа исключения, кроме ExampleError».Однако то, что на самом деле происходит, выглядит примерно так:

try:
    # ...
except (not bool(ExampleError)):
    # ...

Когда в блоке try возникает исключение, Python просматривает различные блоки except в поисках блока, соответствующего типу исключения.Когда он видит except not ExampleError, эквивалентный except (not bool(ExampleError)), это приводит к except False, что недопустимо, поскольку False не является подтипом BaseException (или кортежем подтипов BaseException).Таким образом, код может даже выполняться, если не возникает никаких исключений, но это неправильно.

3 голосов
/ 10 мая 2019

Насколько я знаю, это не будет успешным на любой версии Python. Поскольку оператор not всегда приводит к логическому значению (True или False), он пытается перехватить здесь одно из этих значений, в данном случае False. Поскольку вы не можете бросить True или False, это бесполезно.

Я думаю, что намерение автора было примерно таким:

try:
    raise ExampleError()
except ExampleError e:
    throw e
except:
    raise AnotherExampleError()
1 голос
/ 10 мая 2019

Быстрый тест показывает, что код выдаст ошибку TypeError, если достигнет этой строки:

try:
  raise BaseException
except not BaseException:
  print("Test1")
except BaseException:
  print("Test2")

Исключение:

Во время обработки вышеуказанного исключения произошло другое исключение:

Traceback (последний вызов был последним): файл "main.py", строка 3, в кроме исключений BaseException: TypeError: перехват классов, которые не наследуются от BaseException, не допускается

...