无法访问导入变量

时间:2016-10-16 21:51:41

标签: python python-2.7 import scope global-variables

我是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

由于这些都是全局变量,为什么我没有得到所有打印的全局变量的更新值?

1 个答案:

答案 0 :(得分:1)

解释

在模块A中定义了三个全局变量,在此代码中:

XYZ = "val1"
ABC = {"k1" : "v1", "k2" : "v2"}
PQR = 1

然后新的全局变量XYZABCPQR在模块B中定义,在此代码中:

from A import Cls_A, XYZ, ABC, PQR

这行代码创建了新变量,就像写了以下内容一样:

import A
XYZ = A.XYZ
ABC = A.ABC
PQR = A.PQR

重要的是要理解A.XYZB.XYZ是指向同一对象的两个变量。它们不是同一个变量。

然后将新对象分配给A.XYZ

    XYZ = "val2"

此修改后的A.XYZ,但未修改B.XYZ。这两个变量指向同一个对象,但现在A.XYZ指向不同的对象。

另一方面,A.ABC不与不同的对象相关联。相反,对象本身被修改。修改对象后,A.ABCB.ABC仍然指向同一个对象:

    ABC["k1"] = "z1"
    ABC["k3"] = "v3"

第三种情况也不是对象修改的情况,而是重新分配:

    PQR += 1

该值增加。这创建了一个新对象,而不是将新对象分配给A.PQRB.PQR没有变化。这相当于:

    PQR = PQR + 1

可能不太明显的一点是,Python中的字符串和整数都是不可变的对象(无法将数字更改为2成为3 - 一个人只能为变量分配一个不同的int对象,而不是改变现有的一个。因此,实际上无法以影响A.XYZ的方式更改B.XYZ

字典的行为方式相同

字典“工作”的原因是对象被修改了。如果为A.ABC分配了新的编号,则无效。 E.g。

    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变量,这可能是错误的。始终使用A.XYZ