【问题标题】:Python scoping problemPython范围问题
【发布时间】:2009-07-28 17:38:30
【问题描述】:

我有一个简单的例子:


def func1():
    local_var = None

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

        local_var = "local"

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

func1()

我希望输出是:

第一个 local_var:无 第二个 local_var:本地

但是,我的实际输出是:

第一个本地变量: 回溯(最近一次通话最后): 文件“test.py”,第 13 行,在 函数1() func1 中的文件“test.py”,第 10 行 函数(“第一个”) 文件“test.py”,第 6 行,在 func 中 打印“local_var:”,local_var UnboundLocalError:分配前引用的局部变量“local_var”

我对 python 范围规则的理解表明这应该按预期工作。我有其他代码可以按预期工作,但是将一个不工作的代码片段减少到上面的微不足道的情况也不起作用。所以我被难住了。

【问题讨论】:

    标签: python scoping


    【解决方案1】:

    func 中对local_var 的赋值使其成为局部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,嵌套内部函数引用外部包含函数中的局部变量是完全可以接受的,这就是这个版本所做的一切(分配到barenames与引用到变量不同)。

    【讨论】:

    • 谢谢!这就解释了为什么有时我得到了预期的行为——当我没有在函数中重新分配我的局部变量(在这种情况下是 func() )时,一切都很好。正如您所说,分配给它的行为使它“非常非常本地化”。
    【解决方案2】:

    在 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】:

      在这个相关问题中讨论和解释了 Python 的作用域规则:

      Reason for unintuitive UnboundLocalError behaviour

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 2018-05-24
          • 1970-01-01
          • 2011-11-21
          • 1970-01-01
          • 1970-01-01
          • 2018-12-06
          • 2016-12-18
          • 2010-10-05
          • 1970-01-01
          相关资源
          最近更新 更多