【问题标题】:Why do I get UnboundLocalError in my second code but not in the first?为什么我在第二个代码中得到 UnboundLocalError 而不是在第一个代码中?
【发布时间】:2016-12-01 16:14:39
【问题描述】:

当我执行时

x = 0

def f():
    print('x' in locals())
    x = 1
    print('x' in locals())

f()

我得到了我所期望的,即

False
True

当我执行时

x = 3

def f():
    print(x, 'x' in locals())
    x = 7
    print(x, 'x' in locals())

f()

我希望得到

3 False
7 True

但是我得到了UnboundLocalError

如果 Python 知道下一行在本地范围内分配了标签 x(因此名称 x 已经在本地范围内但尚未分配)那么为什么它让我在我的第一个代码中查询x

已添加

为什么即使x = 7 出现在第一个print(x, 'x' in locals()) 之后,它也会引发错误?

【问题讨论】:

  • 这里仅供参考,但不要在实际代码中使用locals()。或globals()。或eval()。或exec().
  • 首先在locals()中搜索字符"x"。第二个函数尝试使用变量x,然后分配给它。如果要使用全局版本,请指定global x。见*.com/questions/370357/python-variable-scope-error
  • @TigerhawkT3:谢谢。我只是在尝试学习时使用它。
  • @cdarke: 为什么即使x = 7 出现在第一个print(x, 'x' in locals()) 之后,它也会引发错误?
  • 因为有一个编译阶段和一个运行阶段。 Python 的解释方式与 shell 脚本不同。

标签: python


【解决方案1】:

dis.dis 第一个函数:

  2           0 LOAD_CONST               1 ('x')
              3 LOAD_GLOBAL              0 (locals)
              6 CALL_FUNCTION            0
              9 COMPARE_OP               6 (in)
             12 PRINT_ITEM
             13 PRINT_NEWLINE

  3          14 LOAD_CONST               2 (1)
             17 STORE_FAST               0 (x)

  4          20 LOAD_CONST               1 ('x')
             23 LOAD_GLOBAL              0 (locals)
             26 CALL_FUNCTION            0
             29 COMPARE_OP               6 (in)
             32 PRINT_ITEM
             33 PRINT_NEWLINE
             34 LOAD_CONST               0 (None)
             37 RETURN_VALUE

dis.dis 用于第二个功能:

  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 ('x')
              6 LOAD_GLOBAL              0 (locals)
              9 CALL_FUNCTION            0
             12 COMPARE_OP               6 (in)
             15 BUILD_TUPLE              2
             18 PRINT_ITEM
             19 PRINT_NEWLINE

  3          20 LOAD_CONST               2 (7)
             23 STORE_FAST               0 (x)

  4          26 LOAD_FAST                0 (x)
             29 LOAD_CONST               1 ('x')
             32 LOAD_GLOBAL              0 (locals)
             35 CALL_FUNCTION            0
             38 COMPARE_OP               6 (in)
             41 BUILD_TUPLE              2
             44 PRINT_ITEM
             45 PRINT_NEWLINE
             46 LOAD_CONST               0 (None)
             49 RETURN_VALUE

关键区别在于:4 26 LOAD_FAST 0 (x)

基本上,在当前范围内有一个赋值语句来命名x,因此x 被解析为本地名称。解析在编译阶段执行。编译后的字节码使用LOAD_FAST 而不是LOAD_GLOBAL

编译成字节码和执行是two independent steps - 语言实际上并不是逐行解释的。

【讨论】:

    【解决方案2】:

    错误来自打印x,而不是来自调用'x' in locals()。当您执行 'x' in locals() 时,您实际上并没有对变量 x 做任何事情,因为您给它的是一个字符串值,而不是对变量的引用。

    【讨论】:

      最近更新 更多