什么时候Python识别/不识别来自main的变量?

时间:2015-01-13 12:25:48

标签: python variables global-variables python-internals

何时(如果有的话)函数识别已在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

这两种情况有什么区别?

1 个答案:

答案 0 :(得分:1)

简单变量一起使用时,

+=运算符被视为赋值。因此,Python在解析函数体时会在variable中添加<function_object>.func_code.co_varnames,并且由于这一点,在运行期间,Python永远不会在任何其他范围内查找该变量,除非您有global或{{ 1}}声明(仅限Python 3)位于函数顶部。请注意,如果在将nonlocalvariable一起使用之前使用+=并不重要(请参阅上一个示例),该变量现在在函数体中无处不在。

>>> 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_SUBSCR(同样适用于LOAD_ATTR;您可以x.extend([100])但不能x+=[100] 1}};其中x是一个列表)并且因为在将Python视为全局变量(LOAD_GLOBAL)或自由变量之后,没有与dic相关的赋值语句(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