簡體   English   中英

Python 非局部語句/關鍵字

[英]Python nonlocal statement / keyword

nonlocal 在nonlocal 3.x 中做了什么?


要關閉 OP 需要nonlocal但沒有意識到的調試問題,請使用Is it possible to modify variable in python that is in outer, but not global, scope? 反而。

盡管 Python 2從 2020 年 1 月 1 日起正式不受支持,但如果出於某種原因您被迫維護 Python 2.x 代碼庫並且需要等效於 nonlocal ,請參閱nonlocal 2.x 中的 nonlocal 關鍵字

比較一下,不使用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

簡而言之,它允許您將值分配給外部(但非全局)范圍內的變量。 有關所有血腥細節,請參閱PEP 3104

谷歌搜索“python nonlocal”出現了提案, 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

但是,雖然這是完全慣用的 python,但似乎第一個版本對初學者來說會更明顯一些。 通過調用返回的函數來正確使用生成器是一個常見的混淆點。 第一個版本顯式返回一個函數。

它將“最接近”源代碼中的參考點。 這被稱為“詞匯范圍”,並且已經成為標准超過 40 年了。

Python 的類成員實際上在一個名為__dict__的字典中,並且永遠不會通過詞法作用域來訪問。

如果您不指定nonlocal但執行x = 7 ,它將創建一個新的局部變量“x”。 如果您確實指定了nonlocal ,它將找到“最接近的”“x”並分配給它。 如果您指定nonlocal並且沒有“x”,它將給您一條錯誤消息。

關鍵字global對我來說一直很奇怪,因為它會很高興地忽略除最外面的“x”之外的所有其他“x”。

help('nonlocal') nonlocal語句


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

nonlocal語句導致列出的標識符引用最近的封閉范圍內的先前綁定的變量。 這很重要,因為綁定的默認行為是首先搜索本地命名空間。 該語句允許封裝代碼重新綁定全局(模塊)范圍之外的局部范圍之外的變量。

global語句中列出的名稱不同, nonlocal語句中列出的名稱必須引用封閉范圍中的預先存在的綁定(無法明確確定應創建新綁定的范圍)。

nonlocal語句中列出的名稱不得與本地范圍內的預先存在的綁定發生沖突。

也可以看看:

PEP 3104 - 訪問外部范圍內的名稱
nonlocal語句的規范。

相關幫助主題:全局、命名空間

來源: Python 語言參考

引用Python 3 參考

nonlocal 語句導致列出的標識符引用最近的封閉范圍內的先前綁定的變量,不包括全局變量。

如參考資料中所述,在多個嵌套函數的情況下,僅修改最近的封閉函數中的變量:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        x = 2
        innermost()
        if x == 3: print('Inner x has been modified')

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Inner x has been modified

“最近”變量可以在幾個級別之外:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Outer x has been modified

但它不能是全局變量:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    inner()

x = 0
outer()
if x == 3: print('Global x has been modified')

# SyntaxError: no binding for nonlocal 'x' found
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)

我個人對“非本地”語句的理解(請原諒,因為我是 Python 和一般編程的新手)是“非本地”是在迭代函數中使用全局功能而不是代碼本身的一種方式. 如果您願意,可以在函數之間使用全局語句。

使用“非本地”內部函數(即嵌套內部函數)可以獲得外部父函數的特定變量的讀取和“寫入”權限。 nonlocal 只能在內部函數內部使用,例如:

a = 10
def Outer(msg):
    a = 20
    b = 30
    def Inner():
        c = 50
        d = 60
        print("MU LCL =",locals())
        nonlocal a
        a = 100
        ans = a+c
        print("Hello from Inner",ans)       
        print("value of a Inner : ",a)
    Inner()
    print("value of a Outer : ",a)

res = Outer("Hello World")
print(res)
print("value of a Global : ",a)

文檔如下:

nonlocal 語句導致列出的標識符引用最近的封閉 scope 中先前綁定的變量,不包括全局變量。 ...

因此,例如, inner()可以使用非局部x訪問middle()中的非局部變量nonlocal x ,但不能訪問outer()的非局部變量x或 outer outer() ) 外部的全局變量x ,如下所示:

x = 0 # <- ✖
def outer():
    x = 5 # <- ✖
    def middle():
        x = 10 # <- 〇
        def inner():
            nonlocal x # Here
            x += 1
            print(x) # 11
        inner()
    middle()
outer()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM