Функции

Область видимости локальных переменных

Содержание курса

Ловушка: локальная переменная не меняет глобальную с тем же именем

Есть ситуация хитрее, чем NameError: код выполняется без единой ошибки, но результат не тот, что ожидался. Это происходит, когда внутри функции и снаружи существуют переменные с одним и тем же именем.

Посмотрим на пример:

x = 100

def set_x():
    x = 42
    print("внутри функции:", x)  # 42

set_x()
print("снаружи функции:", x)  # 100

Запустите этот код — Python не выдаст никакой ошибки. Но глобальная x так и осталась 100, хотя внутри set_x() мы явно написали x = 42.

Происходит вот что: строка x = 42 внутри функции создаёт новую, отдельную локальную переменную с именем x. Она живёт в пространстве имён функции и никак не связана с глобальной x. Когда set_x() завершается, локальная x исчезает, а глобальная остаётся нетронутой.

Почему это ловушка? Потому что код выглядит «рабочим»: нет ни NameError, ни предупреждений. Если не вывести значения явно, как в примере выше, можно долго не замечать, что функция вообще ничего не сделала с внешней переменной.

Это называют теневым именованием (shadowing): локальное имя «заслоняет» глобальное внутри функции, но не меняет его.

Типичный сценарий, где это приводит к багу:

счётчик = 0

def increment():
    счётчик = счётчик + 1  # UnboundLocalError!

Здесь Python видит присваивание счётчик = ... внутри функции и решает, что счётчик — локальная переменная. Но в правой части присваивания эта же локальная счётчик ещё не существует — и вместо ожидаемого «прибавить 1 к глобальному счётчику» получаем UnboundLocalError.

Правильный подход — не пытаться менять глобальную переменную изнутри функции напрямую. Если функции нужно вернуть новое значение — используйте return:

счётчик = 0

def increment(n):
    return n + 1

счётчик = increment(счётчик)
print(счётчик)  # 1

Функция получает текущее значение через параметр, вычисляет новое и возвращает его. Вызывающий код сам решает, куда сохранить результат. Это и безопаснее, и понятнее: функция не зависит от того, как называется переменная снаружи.

Начать заново?

Помощник начнёт новый диалог по этой задаче. Текущая переписка останется в истории до конца срока хранения.

О переписке

Можно приложить до трёх фото PNG, JPEG или WebP по 5 МБ.

Переписка и фото хранятся 90 дней после последнего принятого сообщения. Преподаватель получит доступ к диалогу, когда вы попросите его помочь.

Проверка решения остаётся отдельным действием.