Внимание! На этой странице вы найдете материал урока из архивного курса по 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.
