关于python:嵌套函数定义和范围(UnboundLocalError)

Nested function definitions and scope (UnboundLocalError)

为什么以下代码无效:

1
2
3
4
5
6
def foo1(x=5):
    def bar():
        if x == 5:
            x = 6
        print(x)
    bar()

当此代码有效时:

1
2
3
4
5
6
def foo2(x=5):
    def bar():
        if x == 5:
            print('ok')
        print(x)
    bar()

foo2()将完全按照您的期望执行,但foo1()将在if x == 5:行给出UnboundLocalError: local variable 'x' referenced before assignment。为什么稍后在代码中更改x的值会使这个条件无效?


python首先需要检测哪些变量是本地的,哪些变量是从外部范围中提取的。为了做到这一点,它会查找作业,例如:

1
2
3
4
5
6
def foo1(x=5):
    def bar():
        if x == 5:
            x = 6 # an assignment, so local variable
        print(x)
    bar()

关键是,任务可以在任何地方进行。例如在最后一行。然而,从现在起,在某个地方,x是本地的。所以在第一个代码片段中,x是一个局部变量。但在分配(有界)之前获取它,所以python会出错。

在python-3.x中,可以使用nonlocal关键字从外部作用域访问x

1
2
3
4
5
6
7
def foo1(x=5):
    def bar():
        nonlocal x
        if x == 5:
            x = 6
        print(x)
    bar()

例如,对于python-2.x,可以将变量赋给函数,例如:

1
2
3
4
5
6
7
def foo1(x=5):
    def bar():
        if bar.x == 5:
            bar.x = 6
        print(bar.x)
    bar.x = x
    bar()

但是请注意,这两个值并不相等。因为在前者中,如果您更改x,它也将更改foo1范围中的x。在后一个示例中,您只修改bar.x。当然,如果这些对象是可变的,您可以更改同一个对象。