nonlocal и изменяемое состояние
Изменяйте область видимости внешней функции
«nonlocal и изменяемое состояние» — бесплатный урок Python Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Python Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Python Academy содержит 4 уроков всего.
Чтение и запись переменных внешней функции
Внутренняя функция может свободно читать переменную внешней функции, но при попытке присвоить значение этому имени Python вместо этого считает его новым локальным именем. Это часто удивляет начинающих.
def outer():
count = 0
def inner():
return count
return inner()
print(outer())Ловушка присваивания
Присваивание значения имени из внешней функции без явного объявления делает это имя локальным, поэтому внешняя переменная не обновляется. Здесь изменение теряется.
def outer():
count = 0
def bump():
count = count + 1
try:
bump()
except UnboundLocalError as e:
print('Error:', e)
outer()Ключевое слово для нелокальной области видимости
nonlocal объявляет, что имя ссылается на переменную в ближайшей внешней области видимости функции. Поэтому присваивания изменяют внешнюю переменную, а не создают локальную.
def outer():
count = 0
def bump():
nonlocal count
count += 1
bump()
bump()
return count
print(outer())Замыкание-счётчик
С помощью nonlocal можно создать счётчик, сохраняющий состояние. Каждый вызов изменяет захваченную переменную и запоминает текущий результат.
def make_counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
c = make_counter()
print(c())
print(c())
print(c())Независимые счётчики
Каждый счётчик хранит собственное состояние, поскольку каждое замыкание захватывает отдельную переменную.
def make_counter():
count = 0
def inc():
nonlocal count
count += 1
return count
return inc
a = make_counter()
b = make_counter()
print(a(), a(), b())Нелокальная и глобальная области видимости
nonlocal обращается к внешней области видимости функции, а global — к уровню модуля. Используйте nonlocal для замыканий, а global — для состояния, общего для всего модуля.
total = 0
def add_global(n):
global total
total += n
add_global(5)
add_global(3)
print(total)Изменяемое состояние без nonlocal
Если внешнее значение является изменяемым объектом, например списком или словарём, его можно изменять на месте без nonlocal, поскольку имя при этом не переназначается.
def make_logger():
history = []
def log(msg):
history.append(msg)
return history
return log
log = make_logger()
log('start')
print(log('stop'))Накопитель
Сочетание nonlocal с замыканием даёт накопитель, который добавляет каждое значение к сохранённой сумме.
def make_accumulator():
total = 0
def add(n):
nonlocal total
total += n
return total
return add
acc = make_accumulator()
print(acc(10))
print(acc(5))
print(acc(100))Простой toggle
Ключевое слово для внешней переменной позволяет легко менять логическое состояние при каждом вызове.
def make_toggle():
on = False
def toggle():
nonlocal on
on = not on
return on
return toggle
t = make_toggle()
print(t(), t(), t())Сброс состояния
Можно предоставить несколько внутренних функций, использующих одно и то же внешнее состояние, например одну функцию add и другую — reset.
def make_bank():
balance = 0
def deposit(n):
nonlocal balance
balance += n
return balance
def reset():
nonlocal balance
balance = 0
return balance
return deposit, reset
deposit, reset = make_bank()
print(deposit(50))
print(reset())nonlocal требует существующей переменной
nonlocal требует, чтобы имя уже существовало во внешней области видимости; иначе Python выдаёт SyntaxError во время определения. Это слово не может создать новую внешнюю переменную.
def outer():
value = 'set'
def inner():
nonlocal value
value = 'changed'
inner()
return value
print(outer())Быстрая проверка
Внутри вложенной функции Вы хотите переназначить переменную из внешней функции. Какое ключевое слово следует использовать?
Повторение: nonlocal и изменяемое состояние
Кратко:
- Присваивание внешнему имени обычно создаёт новое локальное имя;
nonlocalпредотвращает это. nonlocalобращается к области видимости внешней функции, аglobal— к модулю.- Для изменения изменяемого объекта на месте объявление не требуется.
- Замыкания с
nonlocalпозволяют создавать счётчики, накопители и переключатели, которые помнят состояние.
def make_counter():
n = 0
def inc():
nonlocal n
n += 1
return n
return inc
c = make_counter()
print(c(), c())Часто задаваемые вопросы
Урок «nonlocal и изменяемое состояние» бесплатный?
Да — полный текст урока «nonlocal и изменяемое состояние» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Python Academy, подпишись на CoddyKit PRO. Курс Python Academy содержит 4 уроков всего.
Чему я научусь в уроке «nonlocal и изменяемое состояние»?
Изменяйте область видимости внешней функции Ты практикуешь Python Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Python Academy?
Предыдущий опыт не требуется. Python Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «nonlocal и изменяемое состояние»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Python Academy?
Да. Каждый урок Python Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Функции первого класса
- Замыкания и свободные переменные
- nonlocal и изменяемое состояние
- Частичные функции