2011-11-18 75 views
2

可能重复:
Python nested functions variable scoping你可以分配给父函数中定义的变量吗?

多的反复试验后,我已经最终发现,这并不工作:

def a(): 
    def b(): 
     print x 
     x=2 
    x = 1 
    b() 
    print x 

你得到一个异常(X不在被引用之前定义)。所以它看起来像b可以从x中读取,但是如果它试图分配给它,Python会将其'x'的解释更改为局部变量,而现在这个变量尚未定义。

对于我自己病态的好奇心的问题:有什么办法可以实现吗?有没有明确访问父函数范围的方法? (x不是全局的)

+0

重复,除其他外,http://stackoverflow.com/q/5218895/440558 –

+0

是的,你的解释是正确的,Pyhton根据是否有赋值来改变它对“x”的解释在函数体中。至于答案,正如Michael Hoffman所说的那样,在Python 3中,您可以使用“非本地”语句。 – jsbueno

+0

太好了,谢谢。我也搜索过类似的问题,但没有找到。 –

回答

6

Python 3中的nonlocal statement会这样做。


编辑:在Python 2,有没有一个简单的方法来做到这一点。如果你需要这个功能,我建议你使用一些可变的容器对象。例如:

def a(): 
    def b(): 
     print d["x"] 
     d["x"]=2 
    d = dict(x=1) 
    b() 
    print d["x"] 

如果你绝对必须仿效nonlocal对CPython的2,你可以使用Python C API破解这样说:

import ctypes 
import inspect 

locals_to_fast = ctypes.pythonapi.PyFrame_LocalsToFast 
locals_to_fast.restype = None 
locals_to_fast.argtypes = [ctypes.py_object, ctypes.c_int] 

def set_in_frame(frame, name, value): 
    frame.f_locals[name] = value 
    locals_to_fast(frame, 1) 

def a(): 
    def b(frame=inspect.currentframe()): 
     print x 
     set_in_frame(frame, "x", 2) 
    x = 1 
    b() 
    print x 

您还可以设置帧局部,而不是调用PyFrame_LocalsToFast(),则可以操纵a的字节码,以便它使用LOAD_NAME而不是LOAD_FAST。请不要做这些事情。你的用例肯定有更好的解决方案。

+0

......并且暗示,Python 2.x中没有任何东西允许它。 –

+0

不容易!虽然有几种方法可以改变琐事。看到我上面的编辑。 –

+0

哇,很好的编辑:)我看到了分配给变量有什么重要的概念有点微妙。就我而言,确实不需要做任何这些事情(外部函数实际上并不需要修改的值),但是知道这一点很有用。 –

相关问题