2017-10-05 96 views
1

我在函數中使用名稱空間概念尋找一些解釋。函數名稱空間的概念(在賦值之前引用)

下面是這將提高UnboundLocalError代碼:局部變量賦值...

x = 1 
def foo(): 
    print x 
    x = 2 

之前引用我明白了這一點應該引發異常。但我想了解python知道變量是如何在本地命名空間中的。在行print x處,x不在局部變量dict中。

x = 1 
def foo(): 
    print 'local before print x : ',locals() 
    print x 
    print 'local after print x :',locals() 
    x = 2 

foo() # call function, print local namespace before raising exception 
local before print x : {} 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in foo 
UnboundLocalError: local variable 'x' referenced before assignment 

在打印x之前,本地命名空間字典是空{}(這是非常明顯的)。那麼python如何知道x是局部變量。

這與類

a = [1] 
class b(): 
    c = a 
    a = 2 

print 'c inside class ', b.c 
'c inside class [1]' 

d = b() 

不發生異常,在類類似案件的工作方式不同。

如果有人可以幫助我解釋概念,python在賦值之前如何知道這個變量是局部變量。

我查了很多表單和網站的解釋,但沒有找到任何。

有帖子和形式解釋如何解決這種情況。例。 UnboundLocalError: local variable … referenced before assignment。 但我正在尋找Python後面工作。

回答

1

Python將您的代碼預編譯爲一些字節碼。在這一步中,它將查找每個範圍(通常是函數)標識符是引用全局變量還是局部變量。

  • 如果明確聲明爲global,則它是全局的(簡單的情況)。
  • 如果一個值被賦值給它任何地方在函數中沒有被明確地聲明爲global,它是本地的。
  • 如果僅在函數中讀取,則假定爲全局(隱式)。

這是在編譯時完成的,所以沒有執行任何操作來確定它。

現在,在運行時,如果您在分配它之前讀取了局部變量,則會出現錯誤。

現在,類有不同的情況,因爲這些變量並不是真正的本地(即位於調用堆棧的內存中)。如果您在b的聲明中訪問訪問a,您將訪問模塊全局變量,除非存在覆蓋模塊全局變量的類全局變量。如果您將指定爲a,您將創建(或更改)全局類變量。任何後續訪問a(或分配給)將訪問全局類(或分配給)。

+0

是的,我完全同意你的看法。但是當我在打印這個變量之前打印locals()時,它會給出空字典。那麼python如果不在當地人中尋找局部變量,那麼哪裏呢? –

+0

我不明白。如果您在任何地方的函數中都有一個賦值,那麼每個訪問和賦值都將被編譯爲訪問局部變量。如果在運行時發生分配,字典將相應地擴展。如果在分配前完成訪問,字典將缺少條目,這將引發異常。 – Alfe

+0

我想知道,如果該變量在函數中具有賦值,python將查找某處。因爲我知道python首先查看'locals()'內部以檢查該變量是否位於本地命名空間中,而globals()則是全局命名空間。所以在哪個變量python中尋找這種情況。 –