【问题标题】:Python variable resolvingPython变量解析
【发布时间】:2010-08-19 20:35:57
【问题描述】:

给定以下代码:

a = 0
def foo():
  # global a
  a += 1
foo()

运行时,Python 报错:UnboundLocalError: local variable 'a' referenced before assignment

但是,当它是一本字典时......

a = {}
def foo():
  a['bar'] = 0
foo()

事情运行得很好……

有人知道为什么我们可以在第二段代码中引用 a 而不是第一段吗?

【问题讨论】:

    标签: python


    【解决方案1】:

    不同之处在于,在第一个示例中,您分配给 a,这会创建一个新的本地名称 a,它隐藏了全局 a

    在第二个示例中,您没有对a 进行分配,因此使用了全局a

    documentation 对此进行了介绍。

    Python 的一个特殊之处在于——如果没有全局语句生效——对名称的赋值总是进入最内部的作用域。

    【讨论】:

    • 我想知道他们为什么决定将其描述为“特殊的怪癖”?与 a = 1 自动分配给全局范围的 javascript 形成对比!唯一的好处是你可以通过var a = 1的缺失快速识别垃圾代码
    【解决方案2】:

    问题是更新之一。

    您无法更新a,因为它不是您函数的本地命名空间中的变量。就地更新分配操作未能就地更新a

    有趣的是,a = a + 1 也失败了。

    Python 会为这类语句生成略微优化的代码。它使用“LOAD_FAST”指令。

      2           0 LOAD_FAST                0 (a)
                  3 LOAD_CONST               1 (1)
                  6 INPLACE_ADD         
                  7 STORE_FAST               0 (a)
                 10 LOAD_CONST               0 (None)
                 13 RETURN_VALUE        
    

    请注意,在等号的左右两侧使用a 会导致这种优化。

    但是,您可以访问 a,因为 Python 会为您搜索本地和全局命名空间。

    由于a 没有出现在赋值语句的左侧,因此使用了另一种访问方式“LOAD_GLOBAL”。

      2           0 LOAD_CONST               1 (0)
                  3 LOAD_GLOBAL              0 (a)
                  6 LOAD_CONST               2 ('bar')
                  9 STORE_SUBSCR        
                 10 LOAD_CONST               0 (None)
                 13 RETURN_VALUE        
    

    【讨论】:

      【解决方案3】:

      a += 1 等价于a = a + 1。通过分配给变量a,它变成了本地的。您尝试分配 a + 1 的值失败,因为尚未绑定 a

      【讨论】:

        【解决方案4】:

        这是一个非常常见的 Python 陷阱:如果你在函数内分配一个变量(就像你所做的那样,使用 +=),在任何地方(不一定在你以其他方式使用它之前) ),它不使用全局变量。但是,由于您所做的实际上是“a = a + 1”,因此您在分配给它之前尝试访问 a(在表达式的右侧)。

        尝试在函数开头使用 global a(但请注意,您将覆盖全局 a 值)。

        在第二个示例中,您没有将变量 a 分配给它的一项。所以使用了全局字典a

        【讨论】:

          猜你喜欢
          • 2015-05-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-24
          • 2021-11-06
          • 2017-06-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多