Python 何时识别/不识别来自 main 的变量



函数何时(如果有的话)识别已在main函数中初始化的变量?

例如:当我编写以下 Python 代码时:

def plus():
    variable += 1
if __name__ == '__main__': 
    variable = 1
    plus()

我收到以下错误:UnboundLocalError: local variable 'variable' referenced before assignment

但是,当我做类似的事情时,但有一个dictionary

def plus():
    dic[1] += 1
if __name__ == '__main__':
    dic = {}
    dic[1] = 1
    plus()
    print dic[1]

输出为:2

这两种情况有什么区别?

+=运算符在与简单变量一起使用时被视为赋值。因此,Python在解析函数体时会在<function_object>.func_code.co_varnames中添加variable,因此在运行时,Python永远不会在任何其他范围内查找该变量,除非您在函数顶部有globalnonlocal声明(仅限Python 3)。请注意,在将变量与 += 一起使用之前是否使用 variable 并不重要(请参阅上一个示例),变量现在在函数体中的任何地方都是局部的。

>>> def plus():
...     var += 1
...     
>>> dis.dis(plus)
  2           0 LOAD_FAST                0 (var)
              3 LOAD_CONST               1 (1)
              6 INPLACE_ADD         
              7 STORE_FAST               0 (var)
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE   

另一方面,dic[1]变量查找后跟一个BINARY_SUBSCRLOAD_ATTR也是如此;你可以做x.extend([100])但不能x+=[100];其中x是一个列表),因为之后没有与dic相关的赋值语句,Python将其视为全局变量(LOAD_GLOBAL)或自由变量(LOAD_DEREF),并从那里获取其值。

>>> def plus():
    var[0] += 1
...     
>>> dis.dis(plus)
  2           0 LOAD_GLOBAL              0 (var)
              3 LOAD_CONST               1 (0)
              6 DUP_TOPX                 2
              9 BINARY_SUBSCR       
             10 LOAD_CONST               2 (1)
             13 INPLACE_ADD         
             14 ROT_THREE           
             15 STORE_SUBSCR        
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE        
>>> def plus_with_twist():
    var[0] += 1  # this will fail due to the next line
    var += 1     # Now `var` is a local variable everywhere in the function body
>>> dis.dis(plus_with_twist)
  2           0 LOAD_FAST                0 (var)
              3 LOAD_CONST               1 (0)
              6 DUP_TOPX                 2
              9 BINARY_SUBSCR       
             10 LOAD_CONST               2 (1)
             13 INPLACE_ADD         
             14 ROT_THREE           
             15 STORE_SUBSCR        
  3          16 LOAD_FAST                0 (var)
             19 LOAD_CONST               2 (1)
             22 INPLACE_ADD         
             23 STORE_FAST               0 (var)
             26 LOAD_CONST               0 (None)
             29 RETURN_VALUE    

最新更新