Наверняка вы ловили
UnboundLocalError: переменная читалась нормально, ты добавил присваивание ниже в функции — и всё сломалось. Коротко, что происходит на самом деле 👇
🔹 Python не выполняет код построчно
Перед запуском функция компилируется. На этом этапе Python решает, какие переменные локальные, а какие глобальные.
🔹 Одно присваивание = локальная переменная
Если внутри функции есть
x = ..., то x считается локальной во всей функции, даже выше по коду.X = 10
def f():
print(X) # 💥 UnboundLocalError
X = 5
Python заранее решает:
X — локальная → глобальную он даже не проверяет.🔹 Это видно в байткоде
*
LOAD_GLOBAL — поиск в глобальном словаре (медленно)*
LOAD_FAST_CHECK — доступ к слоту локальной переменной (очень быстро)Если переменная помечена как локальная, используется
LOAD_FAST_CHECK.Слот пуст →
UnboundLocalError.Почему так сделано:
🏮 Производительность — локальные переменные лежат в массиве, а не в dict
🏮 Предсказуемость (lexical scoping) — область видимости понятна по коду
🏮 Безопасность — нельзя случайно изменить глобальное состояние
Если нужна именно глобальная:
def f():
global X
print(X)
X = 5
UnboundLocalError — не баг и не «Python сошёл с ума», а следствие компиляции и оптимизаций.Если ошибка указывает на строку чтения — ищи присваивание ниже в функции.
👉 Подробный разбор с dis и байткодом — по ссылке.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст