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

Что происходит при обычном запуске (без -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с указанным сообщением.
Полезная демонстрация: запустить оба варианта


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