是否有可能修改在外部,但不是全球范围内的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()
函数中修改b
variables? 当然,我可以从这里读取和打印(),但如何修改它?
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的对象时,情况就是如此