Можно ли изменить переменную в python, которая находится во внешней, но не глобальной области?
приведенный ниже код:
def A() :
b = 1
def B() :
# I can access 'b' from here.
print( b )
# But can i modify 'b' here? 'global' and assignment will not work.
B()
A()
для кода B()
переменной функции b
В внешней области, но не в глобальной области видимости. Можно ли изменить b
переменной внутри
8 ответов:
Python 3.x имеет
nonlocal
ключевое слово. Я думаю, что это не то, что вы хотите, но я не уверен, если вы используете Python 2 или 3.нелокальный оператор вызывает ссылки на перечисленные идентификаторы ранее связанные переменные в ближайшей охватывающей области. Это важно, потому что поведение по умолчанию для привязки к поиск сначала локальное пространство имен. Оператор позволяет инкапсулированный код повторная привязка переменных вне локальной области кроме глобального (модуль) область применения.
для python 2 я обычно просто использую изменяемый объект (например, список или dict) и мутирую значение вместо переназначения.
пример:
def foo(): a = [] def bar(): a.append(1) bar() bar() print a foo()
выходы:
[1, 1]
вы можете использовать пустой класс для хранения временной области. Это похоже на изменчивое, но немного красивее.
def outer_fn(): class FnScope: b = 5 c = 6 def inner_fn(): FnScope.b += 1 FnScope.c += FnScope.b inner_fn() inner_fn() inner_fn()
это дает следующие интерактивные выход:
>>> outer_fn() 8 27 >>> fs = FnScope() NameError: name 'FnScope' is not defined
Я немного новичок в Python, но я немного читал об этом. Я считаю, что лучшее, что вы получите, похоже на работу Java, которая заключается в том, чтобы обернуть Вашу внешнюю переменную в список.
def A(): b = [1] def B(): b[0] = 2 B() print(b[0]) //output is '2'
Edit: я думаю, это было, вероятно, верно до Python 3. Похоже, что "нелокальный" - это ваш ответ.
нет, вы не можете, по крайней мере, таким образом.
потому что" set operation " создаст новое имя в текущей области, которая охватывает внешний.
для тех, кто смотрит на это гораздо позже, более безопасный, но более тяжелый обходной путь. Без необходимости передавать переменные в качестве параметров.
def outer(): a = [1] def inner(a=a): a[0] += 1 inner() return a[0]
Я не думаю, что вы должны хочу сделать это. Функции, которые могут изменять вещи в их окружающем контексте, опасны, поскольку этот контекст может быть написан без знания функции.
вы можете сделать его явным, либо сделав B публичным методом, а C частным методом в классе (возможно, лучший способ); или используя изменяемый тип, такой как список, и явно передавая его в C:
def A(): x = [0] def B(var): var[0] = 1 B(x) print x A()
вы можете, но вам придется использовать глобальные заявления (не очень хорошее решение, как всегда при использовании глобальных переменных, но оно работает):
def A(): global b b = 1 def B(): global b print( b ) b = 2 B() A()
Я не знаю, есть ли атрибут функция, которая дает
__dict__
внешнего пространства функции, когда это внешнее пространство не является глобальным пространством = = модуль, который имеет место, когда функция является вложенной функцией, в Python 3.но в Python 2, Насколько я знаю, нет такого атрибута.
таким образом, единственные возможности сделать то, что вы хотите:
1) используя изменяемый объект, как говорят другие
2)
def A() : b = 1 print 'b before B() ==', b def B() : b = 10 print 'b ==', b return b b = B() print 'b after B() ==', b A()
результат
b before B() == 1 b == 10 b after B() == 10
.
Примечание
решение Седрика Жюльена имеет недостаток:
def A() : global b # N1 b = 1 print ' b in function B before executing C() :', b def B() : global b # N2 print ' b in function B before assigning b = 2 :', b b = 2 print ' b in function B after assigning b = 2 :', b B() print ' b in function A , after execution of B()', b b = 450 print 'global b , before execution of A() :', b A() print 'global b , after execution of A() :', b
результат
global b , before execution of A() : 450 b in function B before executing B() : 1 b in function B before assigning b = 2 : 1 b in function B after assigning b = 2 : 2 b in function A , after execution of B() 2 global b , after execution of A() : 2
глобальные b после выполнения
A()
была изменена, и это может быть не пожелал такэто только в том случае, если есть объект с идентификатором b в глобальном пространстве имен