【问题标题】:How are variable assignments detected in a function?如何在函数中检测变量赋值?
【发布时间】:2021-11-25 00:20:05
【问题描述】:

尝试执行以下代码时:

a = 1
def test_variable():
    if False:
        a = 2
    print(a)

test_variable()

UnboundLocalError: local variable 'a' referenced before assignment 失败。

这与 Python 中局部变量和全局变量的工作方式一致(source,强调我的):

仅在函数内部引用的变量是隐式全局的。 如果一个变量在函数体中的任何位置被赋值,除非明确声明为全局变量,否则它被假定为局部变量。

但是,当反汇编函数的代码时,我得到:

  5           0 LOAD_GLOBAL              0 (print)
              2 LOAD_FAST                0 (a)
              4 CALL_FUNCTION            1
              6 POP_TOP
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

我们看到变量a 上没有STORE_FAST 指令的踪迹。

因此,我想知道如果字节码中不存在变量赋值,解释器如何知道它?或者,从相反的角度来表述:如果解释器足够聪明,可以完全跳过 if False 块,为什么代码不执行?

【问题讨论】:

  • 即使代码最终通过优化步骤消除,解释器在此之前就已经看到了。显然,在看到分配之后,它决定 a 必须是本地的,因为在此之前它没有被声明为 global

标签: python scope global-variables


【解决方案1】:

解析器检测分配,而不是字节码解释器。因为它在函数的某处看到了赋值,所以它将a 视为局部变量。 LOAD_FAST指令访问局部变量,由于变量不存在而报错。

添加global a 语句并比较生成的反汇编。我想LOAD_FAST会改成LOAD_GLOBAL

【讨论】:

  • 有道理,谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-12
  • 1970-01-01
  • 1970-01-01
  • 2018-05-10
  • 1970-01-01
  • 2018-07-08
  • 1970-01-01
相关资源
最近更新 更多