Python中的本地函数

Mat*_*ner 33 python binding model function local

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

def outer():
    a = 0
    def inner():
        a += 1
    inner()
outer()
Run Code Online (Sandbox Code Playgroud)

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

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

Bre*_*ode 30

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

def outer():
    a = 0
    def inner():
        print a
    inner()
outer()
Run Code Online (Sandbox Code Playgroud)

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

查看此Python 2.6.2文档中"classes"文档的底部部分:

9.2.Python范围和命名空间

[...]如果名称声明为全局,则所有引用和赋值都直接转到包含模块全局名称的中间作用域.否则,最里面的范围之外发现的所有变量都只读(尝试写这样的变量只会在最里面的范围内创建一个新的局部变量,离开同名外变量不变).

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

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

希望有所帮助!

  • 顺便说一句,Python3通过添加非本地语句来解决这个问题:http://docs.python.org/3.1/reference/simple_stmts.html#the-nonlocal-statement (7认同)

小智 10

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

def outer():
a = 0
def inner():
    nonlocal a
    a += 1
inner()
Run Code Online (Sandbox Code Playgroud)

  • 但要注意.我在Python 2.7.6中尝试了这个并且出现了语法错误.根据这个答案,http://stackoverflow.com/a/14264325/1286986,'nonlocal'仅适用于Python 3. (4认同)

Unk*_*own 9

尝试将变量绑定为参数.

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

    inner()

outer()
Run Code Online (Sandbox Code Playgroud)

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

编辑

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

def outer():
    a = [0]
    def inner():
        a[0] += 1
    inner()
    print a[0]
outer()
Run Code Online (Sandbox Code Playgroud)