Python变量作用域的疑问

3
我写了两个简单的函数:

可能是重复问题:
Python作用域规则的简短描述

以下是这些函数:

# coding: utf-8
def test():
    var = 1 
    def print_var():
        print var 
    print_var()
    print var 

test()
# 1
# 1
def test1():
    var = 2 
    def print_var():
        print var 
        var = 3 
    print_var()
    print var 

test1()
# raise Exception

相比之下,test1()print var之后赋值,然后引发异常:UnboundLocalError:local variable 'var' referenced before assignment。我认为当我调用内部的print var时,var的值为2,我错了吗?


1
请查看此链接:https://dev59.com/iXRC5IYBdhLWcg3wD8xV - Hans Then
@HansThen: 不,使用global声明在这里是无效的,因为var是一个函数作用域变量。在Python 3中,你可以使用nonlocal关键字,但是在这个例子中使用的是Python 2,无法实现OP想要做的事情。 - Martijn Pieters
1个回答

1

是的,你在这里是错误的。函数定义引入了一个新的作用域。

# coding: utf-8
def test():
    var = 1 
    def print_var():
        print var    <--- var is not in local scope, the var from outer scope gets used
    print_var()
    print var 

test()
# 1
# 1
def test1():
    var = 2 
    def print_var():
        print var     <---- var is in local scope, but not defined yet, ouch
        var = 3 
    print_var()
    print var 

test1()
# raise Exception

1
等一下,我以为 Python 在执行时不会向前查看。Python 是如何知道 var 在第二个 print_var 函数中将成为一个局部变量的呢? - Lauritz V. Thaulow
所以当Python解析函数时,它会保存一个包含所有在内部赋值的变量名称的列表。然后在调用时,它会检查var是否在这个列表中,并且如果尚未定义,就会报错。这个局部变量列表是否可以访问? - Lauritz V. Thaulow
1
@lazyr:没错,变量在编译时绑定到作用域。赋值是一种存储操作,将该变量绑定到本地作用域除非标记为全局。如果没有赋值,变量就是“自由的”,会在周围的作用域中查找,但这也与特定的作用域绑定在一起。请参考Python带有动态特性的嵌套作用域的示例。 - Martijn Pieters
2
@lazyr:是的,请参考http://docs.python.org/reference/datamodel.html,`afunction.func_code.co_varnames`代表局部变量。`co_freevars`和 co_cellvars在这方面非常有趣;它们分别代表从周围作用域(非全局)引入的变量以及被嵌套函数引用的变量。 - Martijn Pieters
@wim 对的。Martijn回答了我的问题,我找到了这个链接,详细解释了引发UnboundLocalError的词法分析过程。 - Lauritz V. Thaulow
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接