Python 导入模块中的全局变量
我有以下代码:Python 导入模块中的全局变量,python,python-3.x,function,Python,Python 3.x,Function,我有以下代码: one.py import two as t t.test1() t.test2() 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 tes
one.py
import two as t
t.test1()
t.test2()
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)
two.py
import two as t
t.test1()
t.test2()
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:local变量“non_global”
如果我评论non_global=“changed global”
错误就会消失
我的问题是:
为什么这会发生在非全局
而不是obj
?我使用的是python3.5
不同之处在于非全局
是一个变量赋值,而obj.name
是一个属性赋值
函数中的变量赋值使该变量成为局部变量,因此Python不会在局部范围之外的任何地方查找该变量,因此print(non_global)
失败,因为它尚未在该范围内定义。这是用<代码> Global < /Cord>语句进行的,因为使用<代码> Global < /Cord> >您在告诉Python不要将它视为局部变量,因此它的值可以从全局范围获取。
当解析函数体时,将决定是否将变量转换为局部变量,因此在实际声明之前尝试使用该变量的时间将在运行时出现错误
obj.name
另一方面,基本上使用simple搜索obj
,然后使用指定的值设置name
属性
同样,您也可以在函数体中更新全局可变数据结构(列表、dict等),而无需使用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
()
相关:您为什么删除之前的问题,然后重新提问?对obj.name
的赋值不是对obj
的赋值。只有对obj
的赋值才是编译器生成obj
局部变量的依据。@AndyG我认为格式不够好,问这个问题太仓促了。如果test1()
的最后一行是non_global=“changed global”
我就得到了错误。我不明白为什么打印语句后的一行会引起问题。如果这句话被注释了,一切都很好。print语句后面的一行和注释一样好,对吗?@pyjg检查第3段。谢谢,所以函数体被解析,然后逐行执行?我不太明白这个故事flow@pyjg模块或函数的解析会产生字节码,该字节码包含运行时使用的指令。func1
下的指令是从本地作用域(load\u FAST
)加载a
,但该变量当时不存在,因此我们得到了UnboundLocalError
。查看您提供的链接,现在它更有意义了。非常感谢。