python的嵌套函数中局部作用域问题?

查看:127
本文介绍了python的嵌套函数中局部作用域问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

python中赋值操作都会在当前作用域的locals()内部新绑定一个变量。因此如下的代码会报错:

def func1():
    x = 1
    print locals()
    def func2():
        print 'fun2:', locals()
        x += x
        print 'fun2:', locals()

    func2()
    print locals()

if __name__ == '__main__':
    func1()

报错就是

UnboundLocalError: local variable 'x' referenced before ssignment

但是为什么把x改成列表,然后以下面的方式:

def func1():
    x = [1, 2, 3]
    print locals()
    def func2():
        print 'fun2:', locals()
        x[0] += x[0]
        print 'fun2:', locals()

    func2()
    print locals()

if __name__ == '__main__':
    func1()

输出是:

{'x': [1, 2, 3]}
fun2: {'x': [1, 2, 3]}
fun2: {'x': [2, 2, 3]}
{'func3': <function func3 at 0x7f89da00ac08>, 'x': [2, 2, 3], 'func2': <function func2 at 0x7f89da00ab90>}

但是如果把x[0] += x[0]改成x = x[0]又报错了。
求解释啊。。。已经懵了---

解决方案

func2 在 func1 之内,其作用域的范围等同于闭包(至于什么是闭包,详见我的这篇文章:Python 的闭包和装饰器),因此 x 实际上是在父函数 func1 的作用域内,func2 调用它类似于 func1 调用全局变量,只能读取而不能直接改写 x。但是如果你使用列表对象的 x,则 x[0] 并非 x对象 ,而是 x 的元素,因此可以被改写。
其实这是 python 2 的一个bug,在 python 3 中引入了 nonlocal 语句,其类似于 global 语句,只不过是用来声明某个变量是父函数的那个变量,以便于子函数可以直接改写该变量。
在python 2 中,只有用列表对象了,不过在 python 3 中可以这么写:

def func1():
    x = 1
    print(locals())
    def func2():
        nonlocal x       #加上这一句声明这里的 x 是父函数的 x,之后便可以直接改写 x
        print('fun2:', locals())
        x += x
        print('fun2:', locals())

    func2()
    print(locals())

if __name__ == '__main__':
    func1()

具体详见 这里

这篇关于python的嵌套函数中局部作用域问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆