Глава 13 · Автоматизация с помощью функций
Вложенные функции и nonlocal
Функция может быть определена прямо внутри другой функции — а nonlocal позволяет ей изменить имя из объемлющей функции, а не только прочитать его.
Функция внутри функции
Функцию можно определить прямо внутри тела другой функции:
vlozhennaya_funkciya.py
def outer():
message = "Hello"
def inner():
print(message)
inner()
outer()
inner видит message — это и есть Enclosing из LEGB
inner() не имеет своего message, но находит его в объемлющей функции outer() — это буква «E» (Enclosing) из ладдера LEGB (§13.12).Отступ — это не украшение, а объявление вложенности
Если случайно сдвинуть
def inner(): на уровень отступа меньше, чем нужно, она перестанет быть вложенной в outer — и наоборот. Отступ буквально определяет, какая функция находится «внутри» какой.nonlocal
Как и с глобальными переменными, ПРОЧИТАТЬ имя из объемлющей функции можно свободно, а вот ИЗМЕНИТЬ (присвоить) — нужно явно попросить:
nonlocal.py
def outer():
count = 0
def inner():
nonlocal count
count += 1
inner()
inner()
print(count)
outer()
2
nonlocal — это НЕ global
nonlocal ищет имя в БЛИЖАЙШЕЙ подходящей объемлющей функции — не на уровне модуля. Если убрать nonlocal count, получится та же ошибка UnboundLocalError, что и в §13.12 — по той же самой причине: присваивание внутри inner сделало бы count локальным именем самой inner.Чуть глубже — замыкание (closure)
Вложенная функция способна «запомнить» значения из объемлющей функции даже после того, как внешний вызов уже завершился:
closure.py
def make_greeter(name):
def greet():
print(f"Привет, {name}!")
return greet
greet_anna = make_greeter("Anna")
greet_anna() # Привет, Anna! — хотя make_greeter уже закончила работу
Замыкание — тема на будущее
Это называется замыканием —
greet «уносит с собой» доступ к name. Здесь достаточно увидеть, что так вообще бывает — подробный разбор замыканий и их практических применений (декораторы и не только) не входит в эту главу.Практика: вложенные функции и nonlocal
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки