Python非本地语句

时间:2009-08-11 17:36:24

标签: python closures global python-nonlocal

Python nonlocal语句有什么用(在Python 3.0及更高版本中)?

官方Python网站上没有文档,help("nonlocal")也不起作用。

9 个答案:

答案 0 :(得分:385)

比较,不使用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()的{​​{1}}现在也是x的{​​{1}}:< / p>

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

答案 1 :(得分:78)

简而言之,它允许您为外部(但非全局)范围内的变量赋值。有关所有血腥细节,请参阅PEP 3104

答案 2 :(得分:37)

谷歌搜索“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,但似乎第一个版本对于初学者来说会更加明显。通过调用返回的函数正确使用生成器是一个常见的混淆点。第一个版本显式返回一个函数。

答案 3 :(得分:14)

@ooboo:

它与源代码中的参考点“最接近”。 这被称为“词汇范围”,现在是标准的> 40年。

Python的类成员实际上在一个名为__dict__的字典中,并且词汇范围绝不会达到。

如果您未指定nonlocal但指定x = 7,则会创建新的本地变量“x”。 如果您指定nonlocal,它将找到“最接近的”“x”并分配给它。 如果您指定nonlocal且没有“x”,则会显示错误消息。

关键字global对我来说似乎总是很奇怪,因为除了最外层的关键字之外,它会高兴地忽略所有其他“x”。怪异。

答案 4 :(得分:14)

  

帮助( '非局部')   nonlocal声明

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

nonlocal语句导致列出的标识符引用   先前在最近的封闭范围内绑定变量。这是   很重要,因为绑定的默认行为是搜索   本地名称空间首先该语句允许封装代码   除了全局之外,重新定义局部范围之外的变量   (模块)范围。

     

nonlocal语句中列出的名称,与a中列出的名称不同   global语句,必须引用预先存在的绑定   封闭范围(应在其中创建新绑定的范围)   无法明确确定。)

     

nonlocal声明中列出的名称不得与之前发生冲突   本地范围内的现有绑定。

     

另见:

     

PEP 3104 - 访问外部范围内的名称
        nonlocal语句的规范。

     

相关帮助主题:global,NAMESPACES

来源:Python Language Reference

答案 5 :(得分:3)

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)

答案 6 :(得分:2)

我对“非本地”声明的个人理解(并且请原谅我,因为我不熟悉Python和编程)是“非本地”是一种在迭代函数中使用全局功能而不是在代码本身。如果你愿意,可以在函数之间进行全局声明。

答案 7 :(得分:1)

来自Python 3 Reference

的引用
  

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

答案 8 :(得分:0)

带有'非本地'内部函数(即;嵌套内部函数)的

可以读取&amp;对于外部父函数的特定变量,“ '权限。而非本地只能在内部函数中使用 例如:

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)