Is it possible to modify a variable in python that is in an outer (enclosing), but not global, scope?
Можно ли изменить переменную в python, которая находится во внешней (охватывающей), но не глобальной области видимости?
Рассмотрим этот пример:
defA(): b = 1 defB(): # I can access 'b' from here. print(b) # But can i modify 'b' here? B() A()
Для кода в B функции переменная b находится в неглобальной, охватывающей (внешней) области видимости. Как я могу изменить b изнутри B? Я получаю, UnboundLocalError если я попробую это напрямую, и использование global не устраняет проблему, поскольку b не является глобальным.
Оператор nonlocal заставляет перечисленные идентификаторы ссылаться на ранее связанные переменные в ближайшей охватывающей области видимости, исключая глобальные. Это важно, потому что поведение по умолчанию для привязки заключается в том, чтобы сначала выполнить поиск в локальном пространстве имен. Инструкция позволяет инкапсулированному коду повторно связывать переменные за пределами локальной области видимости, помимо глобальной (модульной) области видимости.
deffoo(): a = 1 defbar(): nonlocal a a = 2 bar() print(a) # Output: 2
В Python 2 используйте изменяемый объект (например, список или dict) и изменяйте значение вместо переназначения переменной:
deffoo(): a = [] defbar(): a.append(1) bar() bar() print a
foo()
Выводит:
[1, 1]
Ответ 2
Вы можете использовать пустой класс для хранения временной области видимости. Это похоже на mutable, но немного красивее.
defouter_fn(): classFnScope: b = 5 c = 6 definner_fn(): FnScope.b += 1 FnScope.c += FnScope.b inner_fn() inner_fn() inner_fn()
Это дает следующий интерактивный вывод:
>>> outer_fn() 827 >>> fs = FnScope() NameError: name 'FnScope'isnot defined
Ответ 3
Я немного новичок в Python, но я немного читал об этом. Я считаю, что лучшее, что вы получите, похоже на обходной путь Java, который заключается в том, чтобы обернуть вашу внешнюю переменную в список.
defA(): b = [1] defB(): b[0] = 2 B() print(b[0])
# The output is '2'
Редактировать: Я предполагаю, что это, вероятно, было верно до Python 3. Похоже, nonlocal это ваш ответ.
Ответ 4
Нет, вы не можете, по крайней мере, таким образом.
Потому что "операция set" создаст новое имя в текущей области видимости, которое охватывает внешнюю.