Замыкания

Последнее обновление: 24.01.2022

Замыкание (closure) представляет функцию, которая запоминает свое лексическое окружение даже в том случае, когда она выполняется вне своей области видимости.

Технически замыкание включает три компонента:

  • внешняя функция, которая определяет некоторую область видимости и в которой определены некоторые переменные и параметры - лексическое окружение

  • переменные и параметры (лексическое окружение), которые определены во внешней функции

  • вложенная функция, которая использует переменные и параметры внешней функции

Для определения замыканий в Python применяются локальные функции:

def outer():        # внешняя функция
    n = 5           # лексическое окружение - локальная переменная

    def inner():      # локальная функция
        nonlocal n
        n += 1        # операции с лексическим окружением
        print(n)

    return inner


fn = outer()   # fn = inner, так как функция outer возвращает функцию inner
# вызываем внутреннюю функцию inner
fn()    # 6
fn()    # 7
fn()    # 8

Здесь функция outer определяет локальную переменную n - это и есть лексическое окружение для внутренней функции:

Внутри функции outer определена внутренняя функция - локальная функция inner, которая обращается к своему лексическому окружению - переменной n - увеличивает ее значение на единицу и выводит на консоль:

def inner():      # локальная функция
    nonlocal n
    n += 1        # операции с лексическим окружением
    print(n)

Эта локальная функция возвращается функцией outer:

return inner

В программе вызываем функцию outer и получаем в переменную fn локальную функцию inner:

fn = outer() 

Переменная fn и представляет собой замыкание, то есть объединяет две вещи: функцию и окружение, в котором функция была создана. И несмотря на то, что мы получили локальную функцию и можем ее вызывать вне ее окружающей функции, в которой она определена, тем не менее она запомнила свое лексическое окружение и может к нему обращаться и изменять, что мы увидим по консольному выводу:

fn()    # 6
fn()    # 7
fn()    # 8

Применение параметров

Кроме внешних переменных к лексическому окружению также относятся параметры окружающей функции. Рассмотрим использование параметров:

def multiply(n):
    def inner(m): return n * m

    return inner


fn = multiply(5)
print(fn(5))        # 25
print(fn(6))        # 30
print(fn(7))        # 35

Здесь внешняя функция - multiply возвращает функцию, которая принимает число и возвращает число.

Вызов функции multiply() возвращает локальную функцию inner:

def inner(m): return n * m

Эта функция запоминает окружение, в котором она была создана, в частности, значение параметра n. Кроме того, сама принимает параметр и возвращает произведение параметров n и m.

В итоге при вызове функции multiply определяется переменная fn, которая получает локальную функцию inner и ее лексическое окружение - значение параметра n:

fn = multiply(5)

В данном случае параметр n равен 5.

При вызове локальной функции, например, в случае:

print(fn(6))        # 30

Число 6 передается для параметра m локальной функции, которая возвращает произведение n и m, то есть 5 * 6 = 30.

Также можно было бы сократить этот код с помощью лямбд:

def multiply(n): return lambda m: n * m


fn = multiply(5)
print(fn(5))        # 25
print(fn(6))        # 30
print(fn(7))        # 35
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850