【问题标题】:local variable referenced before assignment (list)赋值前引用的局部变量(列表)
【发布时间】:2021-01-23 16:34:41
【问题描述】:

我遇到了一个有趣的错误。在函数范围之外定义列表时,如下所示,会导致错误:UnboundLocalError: local variable 'a' referenced before assignment

def main():
    a = []
    
    def sub():
        a += ["hello"]
        return a 
    sub()
main()

但是,如果使用相同的逻辑,a.append 不会引发错误

def main():
    a = []
    
    def sub():
        a.append("hello")
        return a 
    sub()
main()

这有什么原因吗?

谢谢

【问题讨论】:

标签: python-3.x


【解决方案1】:

在这种情况下,您必须使用 nonlocal 关键字。
nonlocal documentation

def main():
    a = []
    
    def sub():
        nonlocal a
        a += ["hello"]
        return a 
    sub()
main()

【讨论】:

    【解决方案2】:

    如果您查看生成的 python 字节码。 这部分。

    from dis import dis
    
    def main():
        a = []
        
        def sub():
            a.append(['hello'])
            return a 
        print(dis(sub))
        sub()
    main()
    

    输出

      8           0 LOAD_DEREF               0 (a)
                  2 LOAD_METHOD              0 (append)
                  4 LOAD_CONST               1 ('hello')
                  6 BUILD_LIST               1
                  8 CALL_METHOD              1
                 10 POP_TOP
    
     10          12 LOAD_DEREF               0 (a)
                 14 RETURN_VALUE
    

    您可以看到我们正在使用LOAD_DEREF 将列表中的a 引用加载到函数中。开启时

    from dis import dis
    
    def main():
        a = []
        
        def sub():
            a += ["hello"]
            return a 
        print(dis(sub))
        sub()
    main()
    

    输出

      9           0 LOAD_FAST                0 (a)
                  2 LOAD_CONST               1 ('hello')
                  4 BUILD_LIST               1
                  6 INPLACE_ADD
                  8 STORE_FAST               0 (a)
    
     10          10 LOAD_FAST                0 (a)
                 12 RETURN_VALUE
    

    我们尝试将局部变量a 加载到内存中,并使用LOAD_FAST 指令。这就是为什么会出现错误。如果您使用nonlocal 变量。您将使用LOAD_DEREF 加载变量。

    另请阅读 answer 了解我们这样做的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-02
      • 2011-11-06
      • 2018-01-12
      • 1970-01-01
      相关资源
      最近更新 更多