UnboundLocalError в Python возникает, когда внутри функции переменную читают до того, как ей присвоено значение. Чаще всего это происходит при попытке изменить глобальную переменную прямо в функции. Разберём, почему Python считает такую переменную локальной и как это правильно исправить.
Коротко
Если в функции есть присваивание переменной (x = ...), Python считает её локальной на всю функцию. Попытка прочитать её до присваивания (например, x = x + 1 для внешней x) даёт UnboundLocalError. Правильное решение — не менять внешнюю переменную, а принять её через параметр и вернуть новое значение через return.
Как выглядит ошибка
counter = 0
def increment():
counter = counter + 1
increment()Ошибка выполнения — main.py, строка 4
UnboundLocalError: cannot access local variable 'counter' where it is not associated with a value
Кажется, что функция должна взять глобальный counter, прибавить единицу и записать обратно. Но Python видит присваивание counter = внутри функции и решает: counter — локальная переменная. А раз локальная, то в правой части counter + 1 он читает ещё не созданную локальную переменную — отсюда ошибка.
Почему так происходит
Python определяет область видимости переменной на этапе разбора функции, а не во время выполнения. Правило простое: есть присваивание переменной внутри функции — значит, она локальная во всём теле этой функции, с первой до последней строки. Прочитать снаружи глобальную переменную можно, а вот присвоить ей и одновременно считать «старое» значение — уже конфликт.
Как исправить: параметр и return
Надёжный способ — не лезть в глобальную переменную из функции, а передавать значение через параметр и возвращать результат через return. Так функция становится независимой и предсказуемой.
counter = 0
def increment(value):
return value + 1
counter = increment(counter)
print(counter)1
Функция принимает текущее значение, возвращает новое, а присваивание происходит снаружи. Никакой неоднозначности с областью видимости. Подробнее про параметры, return и область видимости — в гайде Функции в Python: от def до lambda.
А как же global?
Технически ошибку убирает и объявление global counter в начале функции — тогда присваивание идёт в глобальную переменную. Но это плохая практика: функция становится зависимой от внешнего состояния, её сложнее тестировать и переиспользовать. Для новичка правильный выбор почти всегда — параметр и return, а не global.
Где та же ошибка прячется дальше
Ошибку дают все сокращённые операторы над внешней переменной: counter += 1, total -= 5, items *= 2 — это тоже чтение плюс присваивание. Если переменная объявлена снаружи, а внутри функции используется такой оператор без global, будет UnboundLocalError. Решение то же: параметр и return.
Короткие ответы на вопросы
Что значит «referenced before assignment»?
Что переменную попытались использовать до того, как ей присвоили значение. Python уже считает её локальной (из-за присваивания в функции), но значения у неё пока нет.
Почему Python считает переменную локальной?
Потому что внутри функции есть присваивание этой переменной. Само наличие x = ... делает x локальной на всё тело функции, даже если снаружи есть глобальная x.
Что лучше — global или return?
return. Функция, которая принимает данные через параметры и возвращает результат, независима и предсказуема. global связывает её с внешним состоянием и усложняет поддержку.
Кот-наставник— Запомни правило: есть присваивание переменной внутри функции — Python считает её локальной на всю функцию. Отсюда и
UnboundLocalError.— Не чини это через
global. Принимай значение параметром, возвращай черезreturn— и функция перестанет зависеть от того, что творится снаружи.
Область видимости понятнее на практике
На SkillPy ты пишешь функции сам, а AI-наставник показывает, почему переменная стала локальной и где возникает UnboundLocalError. Он понимает твой код и объясняет причину человеческим языком.
