我有以下代码:
one.py
import two as t
t.test1()
t.test2()
two.py
class test_class():
def __init__(self,arg):
print("created obj name is {}".format(arg))
self.name = arg
non_global ="initial global"
obj = test_class("test name")
def test1():
print("\t in test 1")
print (obj.name)
global non_global # wont work without global keyword, value still refers to "initial value"
print(non_global) # initial value
obj.name = "changed"
#non_global = "changed global"
def test2():
print("\tin test 2")
print(obj.name)
print(non_global)
结果是:
created obj name is test name
in test 1
test name
initial global
in test 2
changed
changed global
如果我将 test1()
更改为:
def test1():
print("\t in test 1")
print (obj.name)
#global non_global # wont work without global keyword, value still refers to "initial value"
print(non_global) # initial value
obj.name = "changed"
non_global = "changed global"
我在打印行上收到错误UnboundLocalError:赋值前引用的局部变量“non_global”
。
如果我评论 non_global = "changed global"
错误就会消失。
我的问题是:
为什么这种情况发生在 non_global
而不是 obj
上?我使用的是python 3.5
最佳答案
区别基本上在于,non_global
是变量赋值,而 obj.name
是属性赋值。
函数内的变量赋值使该变量成为局部变量,并且由于 Python 不会在局部范围之外的任何地方查找它,因此 print(non_global)
失败,因为它不是尚未在该范围内定义。这适用于 global
语句,因为通过使用 global
您告诉 Python 不要将其视为局部变量,因此可以从全局范围获取其值。
在解析函数体时会决定变量是否转到局部变量,因此当在实际声明之前尝试使用它时,您将在运行时收到错误。
另一方面,obj.name
基本上使用简单的 LEGB lookup 搜索 obj
然后将 name
属性设置为指定值。
类似地,您也可以在函数体内更新全局可变数据结构(列表、字典等),而无需使用 global
。
除了 =
之外,*=
、+=
等增强赋值也会使变量成为局部变量。
a = []
def func1():
a += ['foo']
def func2():
a.extend(['bar'])
def func3():
a[0] += 'spam'
func1() # Fails with UnboundLocalError: local variable 'a' referenced before assignment
func2() # works fine
func3() # Also works fine because a[0] is not a variable.
# We are telling Python to look for `a` and fetch its 0th item
# and concatenate 'spam' to it.
print(a) # prints ['barspam']
字节码反汇编还可以帮助您指出差异:
>>> import dis
>>> dis.dis(func1)
45 0 LOAD_FAST 0 (a)
3 LOAD_CONST 1 ('foo') # Load a local variable name foo
6 BUILD_LIST 1
9 INPLACE_ADD
10 STORE_FAST 0 (a) # Store local variable named foo
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
>>> dis.dis(func2)
48 0 LOAD_GLOBAL 0 (a) # Load from global scope
3 LOAD_ATTR 1 (extend)
6 LOAD_CONST 1 ('bar')
9 BUILD_LIST 1
12 CALL_FUNCTION 1
15 POP_TOP
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
>>> dis.dis(func3)
51 0 LOAD_GLOBAL 0 (a) # Load from global scope
3 LOAD_CONST 1 (0)
6 DUP_TOPX 2
9 BINARY_SUBSCR
10 LOAD_CONST 2 ('spam')
13 INPLACE_ADD
14 ROT_THREE
15 STORE_SUBSCR
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
# Names of local variables or arguments of each function obtained through its code object
>>> func1.__code__.co_varnames
('a',)
>>> func2.__code__.co_varnames
()
>>> func3.__code__.co_varnames
()
相关:Why am I getting an UnboundLocalError when the variable has a value?
关于python - 导入模块中的全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45357838/