Рубрики
Без рубрики

Python, кроме причуды

Короткий фрагмент Python, который делает что -то совершенно неожиданное. Tagged с Python.

Позвольте мне показать вам мою любимую причуду Python. Что бы вы ожидали, что этот код Python будет делать?

e = 2.718
try:
    1/0
except ZeroDivisionError as e:
    pass
print(e)

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

На самом деле, в стандартной реализации CPYTHON он ничего не печатает; Вместо этого последняя строка поднимает NameError Анкет Это ошибка? На самом деле это было Довольно намеренно Анкет Если вы посмотрите на байт -код, сгенерированный по пункту, вы видите:

LOAD_CONST 0 (None)
STORE_NAME 1 (e)
DELETE_NAME 1

Когда поток управления выходит из кроме Блок, Python удаляет имя из области. Почему? Потому что исключение содержит ссылку на текущую кадр стека, которая содержит Все в рамках. Поскольку Python управляет первичной памятью посредством количества ссылок, это означает, что ничто в текущем сфере не будет освобождено до следующего раунда сбора мусора, если вообще не будет. Текущее поведение – это компромисс между использованием памяти, простотой реализации и чистотой языка. Это немного бородавка, но я думаю, что это воплощает одну из вещей, которые мне нравятся в Python: не позволяя чистоте мешать практичности.

Но это только объясняет Delete_name инструкция Почему Cpython устанавливается E к Нет Если он удалит его сразу после этого? Что ж, представьте, что у вас была та же мысль, что и команда CPYTHON, и решил очистить ссылку на исключение в конце вашего кроме блокировать:

try:
    1/0
except ZeroDivisionError as e:
    ...
    del e

В конце твоего кроме Блок, cpython попытается удалить имя E – Что вы уже удалили! Чтобы обойти это, CPYTHON назначает E Перед удалением E гарантировать, что E существуют.

Оригинал: “https://dev.to/alexbecker/pythons-except-quirk-5ble”