2009-08-11 28 views
174

Python nonlocal語句(在Python 3.0及更高版本中)做什麼?Python非本地語句

在官方Python網站上沒有任何文檔,並且help("nonlocal")也不起作用。

+4

看看這個問題:http://stackoverflow.com/questions/1414304/local-functions-in -python –

+12

下面是nonlocal的官方Python網站文檔:http://docs.python.org/3/reference/simple_stmts.html#the-nonlocal-statement(這篇文檔自Python 3.0開始就已經可用了,所以OP的斷言沒有官方文件是錯誤的) – wkschwartz

+3

''沒有非本地文檔「.'實際上,你可以在Python 3或更高版本中爲文檔操作'help(keyword_in_string)' – ytpillai

回答

254

比較一下,不使用nonlocal

x = 0 
def outer(): 
    x = 1 
    def inner(): 
     x = 2 
     print("inner:", x) 

    inner() 
    print("outer:", x) 

outer() 
print("global:", x) 

# inner: 2 
# outer: 1 
# global: 0 

於此,在使用nonlocal,其中inner() [現在x也是outer()x

x = 0 
def outer(): 
    x = 1 
    def inner(): 
     nonlocal x 
     x = 2 
     print("inner:", x) 

    inner() 
    print("outer:", x) 

outer() 
print("global:", x) 

# inner: 2 
# outer: 2 
# global: 0 

如果我們將使用global,它會結合x到正確的「全球」值:

x = 0 
def outer(): 
    x = 1 
    def inner(): 
     global x 
     x = 2 
     print("inner:", x) 

    inner() 
    print("outer:", x) 

outer() 
print("global:", x) 

# inner: 2 
# outer: 1 
# global: 2 
+25

這與全球x有何不同? – ooboo

+36

它非常相似 - 但請注意,示例中的外部x不是全局的,而是在外部函數中定義的。 – Anon

+0

所以它可以讓你做引用外部變量的內部類,比如java? –

64

簡而言之,它允許您將值分配給外部(但非全局)範圍中的變量。所有血淋淋的細節見PEP 3104

29

谷歌搜索「蟒蛇外地」止跌回升的議案,PEP 3104,這充分說明了語法和推理句話背後。簡而言之,它的工作方式與global聲明完全相同,不同之處在於它用於引用對函數既不是全局變量又不是局部函數的變量。

下面是你可以用這個做什麼的簡要例子。可以重寫計數器生成器以使用它,使其看起來更像是封閉語言的習語。

def make_counter(): 
    count = 0 
    def counter(): 
     nonlocal count 
     count += 1 
     return count 
    return counter 

很明顯,你可以這樣寫發電機,如:

def counter_generator(): 
    count = 0 
    while True: 
     count += 1 
     yield count 

而這是完全地道的蟒蛇,它似乎是第一個版本將是初學者更加明顯一點。正確使用生成器,通過調用返回的函數,是一個常見的混淆點。第一個版本顯式返回一個函數。

+1

我確定這就是關鍵字'global'所做的 - 在更高的環境中工作,直到它達到具有該名稱的變量。變量x可以在模塊級別,類別內部聲明,然後在該類別內的函數中單獨聲明,然後在該函數的內部函數中聲明 - 它如何知道要引用哪個x? – ooboo

+4

關於全局的事情是,它只適用於全局變量。它無法看到封閉的非全局範圍內的變量。 – SingleNegationElimination

+0

我嘗試了make_counter - 但它不會返回一個生成器,而是一個函數。有沒有辦法返回一個生成器,以便我可以迭代它呢? – Dejell

11

@ooboo:

這需要到源代碼參考點的一個「最接近」。 這叫做「詞法範圍」,是現在「40年標準。

Python的類成員是真的在一個名爲__dict__字典和永遠不會被詞法範圍到達。

如果你沒有指定nonlocal,但是做的是x = 7,它會創建一個新的局部變量「x」。 如果指定nonlocal,它會發現「最接近」,「X」,並指定了這一點。 如果指定nonlocal並沒有「X」,它會給你一個錯誤消息。

關鍵字global對我來說一直都很陌生,因爲除了最外面的那個,它會高興地忽略所有其他的「x」。奇怪的。

2

我對「非本地」聲明的個人理解(並原諒我,因爲我是新來的Python和在一般編程)的是,「非本地」是迭代函數中使用全局的功能,而不是身體的方式的代碼本身。功能之間的全局聲明,如果你願意的話。

13

幫助( '外地') 的nonlocal聲明


nonlocal_stmt ::= "nonlocal" identifier ("," identifier)* 

nonlocal語句導致上市標識符指 之前綁定變量在最近的封閉範圍。這是 重要,因爲綁定的默認行爲是首先搜索 本地名稱空間。除了全局的 (模塊)作用域之外,該語句還允許封裝代碼到除局部作用域之外的重新綁定變量 。

名稱在nonlocal語句中列出,不同於那些在 global語句中列出,必須引用預先存在於 封閉範圍綁定(其中一個新的綁定應創建 不能明確地確定的範圍) 。

nonlocal聲明中列出的名稱不得與本地作用域中的現有綁定相沖突。

參見:

PEP 3104 - 在外部範圍
nonlocal聲明規格訪問名稱。

相關幫助主題:全球性的,NAMESPACES

來源:Python Language Reference

+5

每天學習新東西。我不知道你可以在關鍵字上使用'help()'(現在我的想法已經變了:'help()'沒有參數變成_interactive_)。 –

1
a = 0 #1. global variable with respect to every function in program 

def f(): 
    a = 0   #2. nonlocal with respect to function g 
    def g(): 
     nonlocal a 
     a=a+1 
     print("The value of 'a' using nonlocal is ", a) 
    def h(): 
     global a    #3. using global variable 
     a=a+5 
     print("The value of a using global is ", a) 
    def i(): 
     a = 0    #4. variable separated from all others 
     print("The value of 'a' inside a function is ", a) 

    g() 
    h() 
    i() 
print("The value of 'a' global before any function", a) 
f() 
print("The value of 'a' global after using function f ", a)