2011-11-18 58 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

哇,很好的編輯:)我看到了分配給變量有什麼重要的概念有點微妙。就我而言,確實不需要做任何這些事情(外部函數實際上並不需要修改的值),但是知道這一點很有用。 –

相關問題