2013-02-25 56 views
6

TL; DR:我想要一個看起來在包含範圍內的locals()。用於包含範圍的Python本地語言()

大家好。

我正在給一些化學家朋友教授關於Python編程的課程,我想確保我真的瞭解範圍。

考慮:

def a(): 
    x = 1 
    def b(): 
     print(locals()) 
     print(globals()) 
    b() 

當地人打印一個空的環境,全局打印常用的全局。如何訪問存儲x的環境?顯然,口譯員知道這件事,因爲我可以參考它。

相關:何時確定範圍?

def a(): 
    x = 1 
    def b(): 
     a = x+2 
     x = 3 
    b() 

如果您註釋掉X = 3,代碼工作:在= X + 2僅當x = 3包含以下nameErrors。這是否意味着python在解釋它之前對代碼進行了詞彙範圍傳遞?

+0

你需要一個清單嗎?因爲你可以在打印全局變量後打印x。編輯:忘記說,如果你訪問x與打印x然後也是當地人()填充x:1。 – 2013-02-25 22:25:48

+0

可能的重複[在Python中調用命名空間獲取本地](http://stackoverflow.com/questions/6618795/get-locals-from-calling-namespace-in-python) – piokuc 2013-02-25 22:33:27

回答

0

聲明print(locals())是指最近的封閉範圍,即def b():函數。當調用b()時,您將打印本地函數到這個b函數,並且x的定義超出範圍。

def a(): 
    x = 1 
    def b(): 
     print(locals()) 
     print(globals()) 
    b() 
    print(locals()) 

將打印x作爲局部變量。

關於第二個問題:

def a(): 
    x = 1 
    def b(): 
     #a = x+2 
     x = 3 
    b() 

>>> a() 

沒有給出錯誤。

def a(): 
    x = 1 
    def b(): 
     a = x+2 
     #x = 3 
    b() 

>>> a() 

沒有錯誤。

而且

def a(): 
    x = 1 
    def b(): 
     a = x+2 
     x = 3 
    b() 

>>> a() 

給出了以下錯誤:UnboundLocalError: local variable 'x' referenced before assignment

IMO(請),在這第三種情況,在b()身體的第一條語句會在最封閉範圍X 的價值。在這個範圍內,x被分配到下一行。如果您只有語句a = x+2,則x在大多數封閉範圍中都找不到,並且在「下一個」封閉範圍中找到,其中x = 1

6

什麼是你的代碼發生的事情是,當蟒蛇看到在你的b()方法x=3線,它是重新創建xb函數內的範圍,而不是使用x與它的範圍在a功能。

,因爲你的代碼,然後有云:

a = x+2 
    x = 3 

它是說,你需要定義引用它之前的內部範圍的x。但是,當您沒有在b函數內分配x時,python不會嘗試創建一個較低範圍的x,並且不會引發任何錯誤。

將下面的代碼說明這一點:

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

    def c(): 
     print (x) 

    b() 
    c() 
    print (x) 

a() 

但是,如果你要宣佈x作爲global你可以在一個函數中使用它,就像這樣:

def a(): 
    global x 
    x = 1 

    def d(): 
     global x 
     x += 2 

    print (x) 
    d() 
    print (x) 

a() 

的Python 3還增加一個nonlocal關鍵字可以讓你訪問一個封閉範圍內的變量,用法如下:

def a(): 
    x = 1 

    def d(): 
     nonlocal x 
     x += 2 

    print (x) 
    d() 
    print (x) 

a() 

將打印與global示例相同的結果。


如果我錯過閱讀的問題:

按答案Get locals from calling namespace in Python

你可以使用:

import inspect 

def a(): 
    x = 1 

    def d(): 
     frame = inspect.currentframe() 
     try: 
      print (frame.f_back.f_locals) 
     finally: 
      del frame 
    d() 

a() 

得到的函數的局部範圍呼叫者。

+0

可能值得注意的是,Python 3已添加一個'nonlocal'關鍵字,您可以在內部函數中使用該關鍵字以重新綁定封閉範圍中的現有名稱。 – Blckknght 2013-02-25 23:26:44

+0

非常性感!無恥的值得注意的感謝。 – Serdalis 2013-02-26 04:56:03