2014-05-04 32 views
5

Python FAQ,我們可以看到:Python:爲什麼說被引用的變量隱式地是全局的?

在Python中,變量只在函數內部引用隱含全球

而且從Python Tutorial on defining functions,我們可以看到:

函數的執行引入了用於函數局部變量的新符號表。更確切地說,函數中的所有變量賦值都將值存儲在本地符號表中;而變量引用先在局部符號表,然後在封閉函數的局部符號表,然後是全局符號表,終於在表內置名

現在我完全理解教程聲明,但後來說variables that are only referenced inside a function are implicitly global對我來說似乎很模糊。

爲什麼說如果我們實際上開始查看局部符號表,那麼它們就是隱式的全局變量,然後跟着更「普通」的表?這只是一種說法,如果你只是在一個函數中引用一個變量,你不需要擔心它是本地的還是global

回答

7

例子

(見進一步下跌的摘要)

這意味着該如果一個變量從來沒有在一個函數體分配到,那麼它將被作爲全球治療。

這就解釋了爲什麼下面的作品(a被視爲全球):

a = 1 

def fn(): 
    print a # This is "referencing a variable" == "reading its value" 

# Prints: 1 

但是,如果變量被分配到某處函數體,那麼它也將被處理本地爲整個功能體

這包括在之前找到的語句(請參閱下面的示例)。

這解釋了爲什麼不是工作。在這裏,a被視爲本地,

a = 1 

def fn(): 
    print a 
    a = 2 # <<< We're adding this 

fn() 

# Throws: UnboundLocalError: local variable 'a' referenced before assignment 

你可以有Python視變量作爲全球性的發言global a。如果這樣做,那麼該變量將作爲全局對象再次被整個函數體處理。

a = 1 

def fn(): 
    global a # <<< We're adding this 
    print a 
    a = 2 

fn() 
print a 

# Prints: 1 
# Then, prints: 2 (a changed in the global scope too) 

摘要

不像你所期望的是什麼,Python將回落到全球範圍內,如果無法找到在局部範圍a

這意味着變量是本地或全局的對於整個函數體:它不能是全局的,然後變成本地的。

現在,關於變量是作爲本地還是全局對待,Python遵循以下規則。變量是:

  • 全球如果只是引用如果global語句用來
  • 地方如果變量被分配到至少一次(並且不使用global)從未分配到
  • 全球

還注意到

事實上,「意蘊非常全球化「並不意味着全球化。這裏有一個更好的辦法來想一想:

  • 「本地」的意思是「在函數內部某處」
  • 「全球性」的真正含義「之外的功能某處」

所以,如果一個變量被「隱含全局」(==「之外的功能」),那麼它的「封閉的範圍」將被首先擡起頭來:

a = 25 

def enclosing(): 
    a = 2 
    def enclosed(): 
     print a 
    enclosed() 

enclosing() 

# Prints 2, as supplied in the enclosing scope, instead of 25 (found in the global scope) 

現在,像往常一樣,global讓你引用全局SC OPE。

a = 25 

def enclosing(): 
    a = 2 
    def enclosed(): 
     global a # <<< We're adding this 
     print a 
    enclosed() 

enclosing() 

# Prints 25, as supplied in the global scope 

現在,如果你需要分配給aenclosed,並希望a適適用範圍的價值在enclosing改變「,而不是在全球範圍內,那麼你就需要nonlocal,這是新的在Python 3中。在Python 2中,你不能。

1

Python的名稱解析方案有時被稱爲012xx規則,位於範圍 之後。

當您使用不合格的名稱在函數內部,Python的搜索多達四個 範圍,當地(L)範圍,那麼任何封閉(E) DEFS和 lambda表達式,那麼局部範圍全球(G)範圍內,然後內置(B)範圍 - 並停止在 第一個名稱被發現。如果在搜索期間未找到該名稱,則Python 會報告錯誤。

  • 名稱分配默認情況下創建或更改本地名稱。
  • 名稱引用最多搜索四個作用域:local,然後包含 函數(如果有),然後全局,然後內置。
  • 在全局語句和非本地語句中聲明的名稱分別映射指定名稱 以封閉模塊和函數作用域。

換句話說,在函數def聲明(或lambda)中分配的所有名稱默認爲本地語言。函數可以自由使用名稱分配爲 的函數在句法上封裝函數和全局範圍,但是它們必須聲明 如nonlocalsglobals才能更改它們。

參考:http://goo.gl/woLW0F

+2

歸因缺失:[學習Python:強大的面向對象編程](http://goo.gl/woLW0F) –

+0

@Aशwiniचhaudhary完成:) – ajkumar25

1

這是令人困惑和文檔可以站在更清晰。

在這個上下文中的「引用」意味着一個名字不被分配,而是簡單地讀取。因此,例如a = 1被賦值爲a,print(a)(Python 3語法)正在引用a而沒有任何賦值。

如果參考a如上面沒有任何分配,則Python解釋器搜索當前的命名空間的命名空間父遞歸,直到到達全局命名空間。另一方面,如果您將分配給變量,則該變量僅在本地名稱空間內定義,除非使用global關鍵字另外聲明。因此a = 1在本地名稱空間內創建一個新名稱,a。這優先於高級名稱空間中名爲a的任何其他變量。

1

與其他一些語言不同,Python不會在本地符號表中查找變量名稱,然後在沒有找到該變量名稱的情況下回退到更大範圍內查找它。變量在編譯時被確定爲本地的,而不是在運行時,被分配給(包括作爲參數被傳入)。任何未分配給名稱(並且未明確聲明爲全局名稱)的名稱均視爲全局名稱,只能在全局名稱空間中查找。這允許Python優化本地變量訪問(使用LOAD_FAST字節碼),這就是爲什麼當地人更快。

有一些涉及閉包的皺紋(在Python 3中,nonlocal),但這是一般情況。

相關問題