python的嵌套函数中局部作用域问题?
天蓬老师
天蓬老师 2017-04-17 17:17:39
[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]又报错了。
求解释啊。。。已经懵了---

天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

全部回复(2)
大家讲道理

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()

具体详见 这里

阿神

已经解决,思路请见第一条回答及其评论。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号