何时(如果有的话)函数识别已在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
这两种情况有什么区别?
答案 0 :(得分:1)
+=
运算符被视为赋值。因此,Python在解析函数体时会在variable
中添加<function_object>.func_code.co_varnames
,并且由于这一点,在运行期间,Python永远不会在任何其他范围内查找该变量,除非您有global
或{{ 1}}声明(仅限Python 3)位于函数顶部。请注意,如果在将nonlocal
与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_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