从项目中的两个独立脚本访问库中的 class 实例

Accessing a class instance in a library from two separate scripts in a project

我进行了全面搜索,但无法提出合理的搜索查询来产生有用的结果。我将尝试用一个简单的例子(经过测试)来解释这一点。

假设我有一些小型自定义 Python 库,其中仅包含以下私有 class 和 public 实例:

#!/usr/bin/env python

class _MyClass(object):
    def __init__(self):
        self.val = "Default"

my_instance = _MyClass()

现在,我还有另外两个 python 文件('file_a' 和 'file_b'),它们最终将从我的库中导入该实例,如下所示。

完整代码在'file_a':

#!/usr/bin/env python

from my_lib import my_instance

my_instance.val = "File A was here!"
import file_b
file_b.check_val()

完整代码在'file_b':

#!/usr/bin/env python

from my_lib import my_instance

def check_val():
    print "From 'file_b', my_instance.val is: {}".format(my_instance.val)

如果我只在包含 'file_b' 和 'my_lib' 的目录中执行 'file_a',结果输出是:

From 'file_b', my_instance.val is: File A was here!

有人可以向我解释 'file_b' 如何能够访问与我示例中的 'file_a' 完全相同的实例吗?这是否与 'file_a' 中设置的值是全局值有关?

顺便说一下,我知道我可以再次制作 'MyClass' public 并在 'file_a' 或 [ 中需要唯一实例时实例化它=34=],但我发布这个问题的主要原因是想围绕这个特定概念。

如果您在每个文件中 import my_lib 然后 print(id(my_lib)),您将看到只创建了一个模块对象。

阅读The import system from the python docs may help you understand what's going on here. Of particular relevance is the section on The module cache。部分:

The first place checked during import search is sys.modules. This mapping serves as a cache of all modules that have been previously imported, including the intermediate paths. So if foo.bar.baz was previously imported, sys.modules will contain entries for foo, foo.bar, and foo.bar.baz. Each key will have as its value the corresponding module object.

During import, the module name is looked up in sys.modules and if present, the associated value is the module satisfying the import, and the process completes.

这里有两点你需要明白:

1。模块缓存

Python 缓存模块导入以提高性能,即使您执行 from foo import bar 也会发生这种情况。模块对象存储在 sys.modules.

因此,在您的情况下,file_afile_b 正在访问相同的模块对象 my_lib 和相同的实例 my_instance.

2。参考文献

在 Python 中,变量赋值基本上是添加对同一对象的新引用,对于导入也是如此。

from my_lib import my_instance

基本上是

import my_lib
my_instance = my_lib.my_instance
del my_lib

现在我们修改file_a中的这个实例,我们基本上修改了my_lib中的实例,file_b也会看到这个变化。


您可以修改 file_afile_b 来验证这一点。

file_a:

#!/usr/bin/env python

from my_lib import my_instance

my_instance.val = "File A was here!"

print "Inside file_a"
import sys
print id(sys.modules['my_lib']), sys.modules['my_lib'].my_instance, my_instance

import file_b
file_b.check_val()

file_b:

#!/usr/bin/env python

from my_lib import my_instance

print "Inside file_b"
import sys
print id(sys.modules['my_lib']), sys.modules['my_lib'].my_instance, my_instance


def check_val():
    print "From 'file_b', my_instance.val is: {}".format(my_instance.val)

输出(检查对象 ID):

>>> %run file_a.py

Inside file_a
4396461816 <my_lib._MyClass object at 0x106158ad0> <my_lib._MyClass object at 0x106158ad0>
Inside file_b
4396461816 <my_lib._MyClass object at 0x106158ad0> <my_lib._MyClass object at 0x106158ad0>
From 'file_b', my_instance.val is: File A was here!