【问题标题】:How can I have one copy of a variable shared between exactly two modules?如何在两个模块之间共享一个变量的副本?
【发布时间】:2021-01-25 12:45:46
【问题描述】:

我想要一个以全局方式运行的 var 副本:即它的存储存在一次,并且两个模块中对它的所有引用都读取和写入相同的存储。我怎样才能总共使用两个模块来获得这种行为?

这是我的尝试,但失败得很惨:

# module1
#!python

import module2

var = 1

def touch_var():
    global var
    print(var, id(var))
    var = 3
    print(var, id(var))
    
def main():
    global var
    print(var, id(var))
    var = 2
    print(var, id(var))
    module2.do_func()
    print(var, id(var))
    touch_var()
    print(var, id(var))

if __name__ == '__main__':
    main()

# module2
#!python

import module1

def do_func():
    print(module1.var, id(module1.var))
    module1.touch_var()
    print(module1.var, id(module1.var))
    module1.var = 4
    print(module1.var, id(module1.var))

输出是:

1 17006627360
2 17006627392
1 17006627360
1 17006627360
3 17006627424
3 17006627424
4 17006627456
2 17006627392
2 17006627392
3 17006627424
3 17006627424

我已经尝试过使用可变类型的赋值:

#!python

import module2

var = [1]

def touch_var():
    global var
    print(var, id(var))
    var = [3]
    print(var, id(var))
    
def main():
    global var
    print(var, id(var))
    var = [2]
    print(var, id(var))
    module2.do_func()
    print(var, id(var))
    touch_var()
    print(var, id(var))

if __name__ == '__main__':
    main()

#!python

import module1

def do_func():
    print(module1.var, id(module1.var))
    module1.touch_var()
    print(module1.var, id(module1.var))
    module1.var = [4]
    print(module1.var, id(module1.var))

我得到了这个结果:

[1] 7696579790600
[2] 7696579792072
[1] 7696579790664
[1] 7696579790664
[3] 7696579790600
[3] 7696579790600
[4] 7696579790664
[2] 7696579792072
[2] 7696579792072
[3] 7696579790600
[3] 7696579790600

我已经尝试分配给可变类型的元素:

#!python

import module2

var = [1]

def touch_var():
    global var
    print(var, id(var))
    var[0] = 3
    print(var, id(var))
    
def main():
    global var
    print(var, id(var))
    var[0] = 2
    print(var, id(var))
    module2.do_func()
    print(var, id(var))
    touch_var()
    print(var, id(var))

if __name__ == '__main__':
    main()

#!python

import module1

def do_func():
    print(module1.var, id(module1.var))
    module1.touch_var()
    print(module1.var, id(module1.var))
    module1.var[0] = 4
    print(module1.var, id(module1.var))

我得到了这个结果:

[1] 7696579790600
[2] 7696579790600
[1] 7696579790664
[1] 7696579790664
[3] 7696579790664
[3] 7696579790664
[4] 7696579790664
[2] 7696579790600
[2] 7696579790600
[3] 7696579790600
[3] 7696579790600

所有三个都给出相同的结果。

我想要的输出是这样的:

1
2
2
2
3
3
4
4
4
3
3

为什么我得到我得到的?我怎样才能得到我想要的?

请注意,这不是“Python:在其中的模块和类之间共享全局变量”的副本,正如@prune 所假设的那样,因为在那个答案中,问题是由使用“from module import *”引起的,它我不在这里做;另一个答案是问题来自使用不可变类型,我已经证明这不是问题。此外,我的标准之一是使用两个文件来解决此问题,但该问题使用三个文件。

【问题讨论】:

    标签: python python-import main


    【解决方案1】:

    您的问题来自循环导入这一事实。您正在 module1 中运行代码以启动。这将创建一个 module1 命名空间的副本。然后,您从模块 1 调用模块 2 中的代码,其中模块 2 也导入模块 1。在 module2 中调用 import module1 正在创建 module1 命名空间的第二个副本。

    这就是为什么您在 module2 中的第一次调用会打印 1,因为这是它在 module1.py 中最初设置的值,而您刚刚导入了它。 module2 中的所有调用,甚至那些调用 module1 的调用,都在处理 module1 的第二个副本。

    这就是为什么当您退出对模块 2 的调用并返回模块 1 时,您的变量又回到了 2 的值,即调用模块 2 之前的值。通过调用模块 2,模块 1 的原始副本没有任何变化,模块 2 始终在模块 1 的第二个副本上运行。

    这是一种说服自己正在发生这种情况的方法。制作一个名为 module3.py 的 module1.py 的副本,并将其包含在 module2.py 中,而不是 module1.py。您将得到完全相同的结果,但现在很清楚发生了什么,因为您不会期望 module1 中的 var 和 module3 中的那个是同一个变量。

    【讨论】:

      【解决方案2】:

      这里有一个简单的解决方法:

      #!python
      # module2
      
      import __main__ as module1
      

      您的示例无法按预期运行的原因是,执行的脚本始终作为“__main__”添加到sys.modules。因此,当您稍后使用其文件名 导入它时,您将获得对不同模块对象的引用。在这方面,它有些特殊处理,因为重新导入任何其他模块将始终引用 sys,modules 中的同一对象。

      (注意:虽然上述修复解决了您的问题,但它是usually considered bad practice)。

      【讨论】:

        猜你喜欢
        • 2019-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多