assert и __debug__ в Python: почему выводится True, затем AssertionError

assert и __debug__ в Python: почему выводится True, затем AssertionError

@python_quiz

Разберем этот квиз

Кратко про задачу: в коде печатается значение встроенной константы __debug__, а затем вызывается функция, в которой стоит оператор assert перед делением на y. Нам нужно понять, что напечатает и какое исключение возникнет при обычном запуске и при использовании оптимизации (-O).

Исходный код

python

Что происходит при обычном запуске (без -O)

  • __debug__ — встроенная константа: по умолчанию она равна True.
  • assert — оператор, который проверяет условие во время выполнения и при ложном значении возбуждает AssertionError.
  • В функции assert проверяется y != 0; так как y == 0, assert выполняется и возбуждает AssertionError до того, как произойдёт операция деления.

Ожидаемый результат при обычном запуске (например, python3 script.py):

(в реальной консоли вместо одной строки вы увидите сначала True , затем стек вызовов с сообщением AssertionError: zero.)

Что происходит при запуске с -O (оптимизация)

  • При запуске интерпретатора с ключом -O (например, python3 -O script.py) значение __debug__ становится False.
  • Операторы assert полностью удаляются при компиляции в оптимизированном режиме, поэтому проверка assert y != 0 не выполняется и не возбуждает AssertionError.
  • Тогда пытаются выполнить x / y, что вызывает ZeroDivisionError.

Ожидаемый результат при python3 -O script.py:

Анализ предложенных вариантов ответа

  • "Выведет: True, затем AssertionError" — соответствует поведению при обычном запуске без -O: сначала True, затем AssertionError (сообщение 'zero').
  • "Выведет: False, затем AssertionError" — неверно: если __debug__ False (т.е. запуск с -O), assert удаляется, поэтому AssertionError не возникает.
  • "Выведет: True, затем ZeroDivisionError" — неверно: при обычном запуске assert остаётся и перехватывает ситуацию до деления, поэтому возникает AssertionError, а не ZeroDivisionError.
  • "Выведет: False, затем ничего не выведет" — неверно: при False assert удалён, дальше выполняется деление на ноль и возникает ZeroDivisionError (то есть вместо «ничего» будет исключение).

Короткие выводы и правила на будущее

  • __debug__ — константа, меняется на False при запуске с -O.
  • assert удаляется в оптимизированном режиме (-O), поэтому не полагайтесь на assert для проверок, нужных в продакшене.
  • Порядок операций важен: assert выполняется до выражения деления, поэтому при срабатывании он предотвращает ZeroDivisionError и вызывает AssertionError с указанным сообщением.

Полезная демонстрация: запустить оба варианта

bash
bash

Эти короткие эксперименты подтвердят описанное поведение.

Report Page