我是python的新手,在理解这里的作用域时遇到了一些问题。
我有一个python模块a,它有三个全局变量:
XYZ = "val1"
ABC = {"k1" : "v1", "k2" : "v2"}
PQR = 1
class Cls_A() :
def sm_fn_A(self) :
global XYZ
global ABC
global PQR
XYZ = "val2"
ABC["k1"] = "z1"
ABC["k3"] = "v3"
PQR += 1
另一个模块B:
from A import Cls_A, XYZ, ABC, PQR
class Cls_B():
def sm_fn_B(self) :
Cls_A().sm_fn_A()
print XYZ
print ABC
print PQR
Cls_B().sm_fn_B()
这给了我以下输出:
val1
{'k3': 'v3', 'k2': 'v2', 'k1': 'z1'}
1
既然这些都是全局变量,为什么我不打印所有全局变量的更新值?
说明
模块A
中定义了三个全局变量,在此代码中:
XYZ = "val1"
ABC = {"k1" : "v1", "k2" : "v2"}
PQR = 1
然后在模块B
中定义新的全局变量XYZ
、ABC
、PQR
,在该代码中:
from A import Cls_A, XYZ, ABC, PQR
这行代码创建了新的变量,就像写了以下内容一样:
import A
XYZ = A.XYZ
ABC = A.ABC
PQR = A.PQR
重要的是要理解A.XYZ
和B.XYZ
是指向同一对象的两个变量。它们不是同一个变量。
然后将一个新对象分配给A.XYZ
:
XYZ = "val2"
这修改了A.XYZ
,但没有修改B.XYZ
。这两个曾经是指向同一对象的两个变量,但现在A.XYZ
指向不同的对象。
另一方面,A.ABC
不与不同的对象相关联。相反,对象本身会被修改。修改对象时,A.ABC
和B.ABC
仍然指向同一对象:
ABC["k1"] = "z1"
ABC["k3"] = "v3"
第三种情况也不是对象修改的情况,而是重新分配:
PQR += 1
该值已递增。这创建了一个新对象,然后将该新对象分配给A.PQR
。CCD_ 16不变。这相当于:
PQR = PQR + 1
一件可能并不明显的事情是,字符串和整数在Python中都是不可变的对象(无法将数字更改为2
以变为3
——只能为变量分配一个不同的int对象,而不能更改现有对象(。因此,实际上没有办法以影响B.XYZ
的方式更改A.XYZ
。
字典也可以这样
使用字典"工作"的原因是对象被修改了。如果一个新的dictionary被分配给A.ABC
,那将不起作用。例如
ABC = {'k3': 'v3', 'k2': 'v2', 'k1': 'z1'}
现在它不会影响B.ABC
,因为A.ABC
中的对象没有更改。另一个对象被分配给A.ABC
。
与模块无关
在没有任何模块的情况下也可以看到相同的行为:
A_XYZ = "val1"
A_ABC = {"k1" : "v1", "k2" : "v2"}
A_PQR = 1
B_XYZ = A_XYZ
B_ABC = A_ABC
B_PQR = A_PQR
A_XYZ = "val2"
A_ABC["k1"] = "z1"
A_ABC["k3"] = "v3"
A_PQR += 1
print B_XYZ
print B_ABC
print B_PQR
打印:
val1
{'k3': 'v3', 'k2': 'v2', 'k1': 'z1'}
1
解决方案
好吧,不要一直引用临时对象。使用具有正确值的变量。
例如,在模块B
:中
import A
class Cls_B():
def sm_fn_B(self) :
A.Cls_A().sm_fn_A()
print A.XYZ
print A.ABC
print A.PQR
Cls_B().sm_fn_B()
现在实际上没有B.XYZ
变量,这可能是错误的。始终使用CCD_ 27。