Python范围问题

时间:2009-07-28 17:38:30

标签: python scoping

我有一个简单的例子:


def func1():
    local_var = None

    def func(args):
        print args,
        print "local_var:", local_var

        local_var = "local"

    func("first")
    func("second")

func1()

我希望输出为:

first local_var: None
second local_var: local

但是,我的实际输出是:

first local_var:
Traceback (most recent call last):
  File "test.py", line 13, in 
    func1()
  File "test.py", line 10, in func1
    func("first")
  File "test.py", line 6, in func
    print "local_var:", local_var
UnboundLocalError: local variable 'local_var' referenced before assignment

我对python范围规则的理解要求这应该按预期工作。我有其他代码,这可以按预期工作,但减少一个非工作代码片段到它上面的小部分情况也不起作用。所以我很难过。

4 个答案:

答案 0 :(得分:9)

local_var中对func的分配使其本地func - 因此print语句引用“非常本地”变量在它被分配之前变量,正如例外所述。正如jtb所说,在Python 3中你可以使用nonlocal来解决这个问题,但是使用print语句从代码中可以清楚地知道你在Python 2中工作.Python 2中的传统解决方案是确保赋值不是一个名字,因此不会使变量比你想要的更加局部,例如:

def func1():
    local_var = [None]

    def func(args):
        print args,
        print "local_var:", local_var[0]

        local_var[0] = "local"

    func("first")
    func("second")

func1()

索引的赋值不是一个简单的名称,因此不会影响局部性,因为Python 2.2嵌套的内部函数完全可以接受引用到外部包含函数的本地变量,这就是所有这个版本(分配到裸名称是一个与引用到变量不同的问题)。

答案 1 :(得分:1)

在Python 3.0之前,函数无法写入外部作用域中的非全局变量。 Python3引入了nonlocal关键字,可以让它工作。您可以在nonlocal local_var定义的顶部添加func()以获得您期望的输出。请参阅PEP 3104

如果您不使用Python 3,则必须将变量设为全局变量,或以某种方式将其传递给函数。

答案 2 :(得分:1)

3.0之前解决此问题的标准方法是

def func1():
    local_var = [None]

    def func(args):
        print args,
        print "local_var:", local_var[0]

        local_var[0] = "local"

    func("first")
    func("second")

func1()

答案 3 :(得分:1)

Python的范围规则在相关问题中进行了讨论和解释:

Reason for unintuitive UnboundLocalError behaviour