是否有可能修改在外部,但不是全球范围内的Python的variables?

鉴于下面的Python 2.7代码:

def A() : def B() : b = 1 def C() : # I can access 'b' from here. print( b ) # But can i modify 'b' here? 'global' and assignment will not work. C() print( b ) B() A() 

对于C()的代码,函数variablesb在外部范围内,但不在全局范围内。 是否有可能从C()函数中修改bvariables? 当然,我可以从这里读取和打印(),但如何修改它?

Python 3.x有nonlocal关键字 。 我认为这是你想要的,但我不知道你是否正在运行Python 2或3。

nonlocal语句会使列出的标识符引用最近的封闭范围中的以前绑定的variables。 这很重要,因为绑定的默认行为是首先search本地名称空间。 该语句允许封装代码除了全局(模块)作用域之外还重新绑定局部作用域之外的variables。

对于Python 2,我通常只使用可变对象(如列表或字典),并改变值而不是重新分配。

例:

 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解决方法类似,即将外部variables包装在列表中。

 def A(): b = [1] def B(): b[0] = 2 B() print(b[0]) //output is '2' 

编辑:我猜这可能是真正的Python 3之前。看起来像“nonlocal”是你的答案。

不,你至less不能这样做。

因为“设置操作”将在当前范围内创build一个新的名称,它覆盖了外部名称。

对于任何人来说,这是一个更安全,但更重的解决方法。 不需要传递variables作为参数。

 def outer(): a = [1] def inner(a=a): a[0] += 1 inner() return a[0] 

你可以,但是你将不得不使用全局语句 (在使用全局variables的时候不是一个非常好的解决scheme,但是它可以工作):

 def A() : def B() : global b b = 1 def C() : # I can access 'b' from here. global b print( b ) b = 2 # But can i modify 'b' here? 'global' and assignment will not work. C() print( b ) B() A() 

我不认为你应该这样做。 可以在封闭的上下文中改变事物的函数是危险的,因为可以在不知道函数的情况下编写上下文。

你可以明确地说,把B作为一个公开的方法,C把一个私有的方法放在一个类中(最好的方法)。 或者通过使用可变types(如列表)并将其明确传递给C:

 def A(): x = [0] def B(var): var[0] = 1 B(x) print x A() 

我不知道当这个外层空间不是全局空间的时候,是否有一个函数的属性赋予了函数外层空间的__dict__ ==模块,当函数是嵌套函数时,在Python 3中。

但在Python 2中,据我所知,没有这样的属性。

所以唯一可能做你想做的是:

1)使用可变对象,如其他人所说

2)

 def A() : def B() : b = 1 print 'b before C() ==',b def C() : # I can access 'b' from here. b = 10 print'b ==',b return b b = C() print'b after C() ==', b B() A() 

结果

 b before C() == 1 b == 10 b after C() == 10 

诺塔

CédricJulien的解决scheme有一个缺点:

 def A() : def B() : global b # N1 b = 1 print ' b in function B before executing C() :',b def C() : # I can access 'b' from here. global b # N2 print ' b in function C before assigning b = 2 :',b b = 2 print ' b in function C after assigning b = 2 :',b # But can i modify 'b' here? 'global' and assignment will not work. C() print ' b in function B , after execution of C()',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 C() : 1 b in function C before assigning b = 2 : 1 b in function C after assigning b = 2 : 2 b in function B , after execution of C() 2 global b , after execution of A() : 2 

A()执行后的全局b已被修改,可能不是这样的

只有在全局名称空间中有标识符为b的对象时,情况就是如此