Codebra
29 января 2026 в 18:34

Урок 50. Замыкания и оператор nonlocal в Python

В этом уроке мы поговорим о замыканиях и операторе nonlocal в Python.
📝

Внимание! На этой странице вы найдете материал урока из архивного курса по Python. Курс был написан в 2024 году и по-прежнему актуален для начинающих разработчиков.

Теоретический материал сохранен в исходном виде, а практические задания с автоматической проверкой вынесены в отдельные интенсивы и задания.

Полный список уроков доступен по тегу Архивный курс по Python и на странице первого урока.

📝 Кратко
  • Замыкание в Python - функция, ссылающаяся на переменные из внешней функции.
  • Обычная функция имеет доступ к своим аргументам и глобальным переменным.
  • Внутренняя функция создается при каждом выполнении внешней функции.
  • Замыкание сохраняет ссылки на переменные внешней функции до выполнения вложенной функции.
  • Пример: функция inner() является замыканием, mult_by_2 ссылается на inner().
  • Замыкания напоминают классы в способности запоминать значения свободных переменных.
  • Пример: calc_obj = calc(10, 2), calc_obj.add() и calc_obj.sub() возвращают 12 и 8 соответственно.

В предыдущем уроке мы разобрались с областью видимости в Python. Сейчас будем разбираться с замыканиями. Тема достаточно непростая для понимания начинающему программисту. Хотя если вы дошли до этого урока, то обязательно разберетесь с замыканиями, не сомневайтесь.

Замыкание (англ. closure) – это функция, которая ссылается на переменные из внешней функции в области видимости которой она находится. Обычной функции доступны свои аргументы и глобальные переменные – в этом различие.

Внутренняя функция создается при каждом выполнении внешней. Таким образом, каждый раз создается новый экземпляр с обновленными ссылками на переменные внешней функции. Эти ссылки действительны до тех пор, пока выполняется вложенная функция.

Согласен, немного непонятно, поэтому рассмотрим пример:

def mult(num1):
    def inner(num2):
        return num1 * num2
    return inner

mult_by_2 = mult(2) # ссылается на inner()
print(mult_by_2(2)) # => 4

В данном примере функция inner() является замыканием. Так же необходимо понимать в какой момент происходит запоминание значения. Для этого рассмотрим пример:

def mult(num1):
    x = 1
    def inner(num2):
        return num1 * num2 + x
    x = 10
    return inner
mult_by_2 = mult(2)
print(mult_by_2(2))

На первый взгляд можно предположить, что результатом будет число 5, но нет.

Рассмотрим следующий пример:

def mult(num1):
    a = 10
    def inner(num2):
        a += 1
        return num1 * num2 + a
    return inner

mult_by_2 = mult(2)
print(mult_by_2(2))

Выполнение этого кода вызовет ошибку. Переменная a является свободной, поэтому чтобы ее менять с сохранением измененного значения между вызовами, следует использовать оператор nonlocal:

def mult(num1):
    a = 10
    def inner(num2):
        nonlocal a
        a += 1
        return num1 * num2 + a
    return inner

Для обыкновенного присваивания значения переменной a, оператор nonlocal использовать не нужно. Например, nonlocal можно использовать следующим способом:

def up(num1):
    a = num1
    def inner():
        nonlocal a
        a -= 1
        return a
    return inner

up_one = up(10)
print(up_one()) # => 9
print(up_one()) # => 8
print(up_one()) # => 7
print(up_one()) # => 6

Замыкания из-за умения запоминать значения свободных переменных чем-то напоминают классы (о них мы будем говорить позднее). Далее пример:

def calc(a, b):
    def add():
        return a + b
    def sub():
        return a - b

    calc.add = add
    calc.sub = sub
    return calc

calc_obj = calc(10, 2)
print(calc_obj.add()) # => 12
print(calc_obj.sub()) # => 8

В этом уроке познакомились с замыканиями в Python и ситуациями, когда следует использовать оператор nonlocal. Далее будем говорить об аргументах функции.

📝

Переходите к следующему уроку курса, а так же не забудьте посмотреть новый материал на Codebra по тегу Python.