【问题标题】:Unable to access modified value of imported variable无法访问导入变量的修改值
【发布时间】:2016-10-16 21:51:40
【问题描述】:

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

既然这些都是全局变量,为什么我没有打印出所有全局变量的更新值?

【问题讨论】:

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


    【解决方案1】:

    说明

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

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

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

    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 对象到一个变量,而不是改变现有的)。因此,实际上无法以影响B.XYZ 的方式更改A.XYZ

    字典的行为方式可能相同

    使用字典“工作”的原因是对象被修改了。如果一个新的字典被分配给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 变量,这可能是错误的。始终使用A.XYZ

    【讨论】:

    • 我对导入机制的不清楚可能让我感到困惑。你已经解释得很完美了。非常感谢,这个答案很有意义。
    猜你喜欢
    • 1970-01-01
    • 2016-12-12
    • 2019-05-14
    • 2011-04-09
    • 2019-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多