Python中的本地函数

时间:2009-09-12 04:45:08

标签: python function binding model local

在下面的Python代码中,我得到了一个UnboundLocalError。据我所知,局部函数共享包含函数的局部变量,但这似乎不是这里的情况。我认识到a在这种情况下是一个不可变的值,但这应该不是问题。

def outer():
    a = 0
    def inner():
        a += 1
    inner()
outer()

看起来内部函数已经收到了父函数中所有引用的副本,因为如果UnboundLocalError的值包含在一个可变类型中,我就不会得到a异常。

有人能够澄清这里的行为,并指出相应的Python文档吗?

3 个答案:

答案 0 :(得分:30)

我认为你认为这是一个“可变性”问题是正确的。虽然您发布的代码会抛出“UnboundLocalError”,但以下代码不会:

def outer():
    a = 0
    def inner():
        print a
    inner()
outer()

Python不允许您从内部作用域中的外部作用域重新分配变量的值(除非您使用关键字“global”,在这种情况下不适用)。

查看本Python 2.6.2文档中“classes”文档的底部:

  

9.2. Python Scopes and Namespaces

     

[...]如果名称被声明为全局,则所有引用和分配都会进行   直接到包含模块全局名称的中间范围。   否则,在最内层范围之外找到的所有变量都是   只读(尝试写入这样的变量只会创建一个   最内层范围内的新局部变量,保持相同   命名外部变量不变)。

你的“UnboundLocalError”是因为你的函数实际上声明了一个名为“a”的新变量,然后立即尝试对其执行“+ =”操作,但这失败了,因为“a”还没有值。 (将“a + = 1”视为“a = a + 1”,如果“a”未定义,您可以看到问题。)

一般来说,如果你想要修改“a”,人们通常会绕过它的方式是使用一个可变类型来传递“a”(例如列表或字典)。您可以通过可变类型的内容修改“a”(正如您在使用此设置进行测试时可能注意到的那样)。

希望有所帮助!

答案 1 :(得分:10)

您应该将变量指定为非本地变量以在闭包中保留它的状态,因此定义应该是这样的

def outer():
a = 0
def inner():
    nonlocal a
    a += 1
inner()

答案 2 :(得分:9)

尝试将变量绑定为参数。

def outer():
    a = 0
    def inner(a=a):
        a += 1

    inner()

outer()

我会尝试挖掘相应的文件。

修改

由于您希望内部函数对外部作用域产生副作用,因此您需要使用类似列表的可变数据类型。整数和字符串是不可变的。

def outer():
    a = [0]
    def inner():
        a[0] += 1
    inner()
    print a[0]
outer()