从项目中的两个单独的脚本访问库中的类实例

Dan*_*ger 5 python import scoping

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

假设我有一些小的自定义Python库,其中仅包含以下私有类和公共实例:

#!/usr/bin/env python

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

my_instance = _MyClass()
Run Code Online (Sandbox Code Playgroud)

现在,我还有另外两个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()
Run Code Online (Sandbox Code Playgroud)

“ 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)
Run Code Online (Sandbox Code Playgroud)

如果仅在还包含“ file_b”和“ my_lib”的目录中执行“ file_a”,则结果输出为:

#!/usr/bin/env python

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

my_instance = _MyClass()
Run Code Online (Sandbox Code Playgroud)

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

顺便说一句,我确实知道我可以再次公开“ MyClass”,并在“ file_a”或“ file_b”中需要唯一实例时将其实例化,但是我发布此问题的主要原因是为了解决问题这个特定的概念。

Ash*_*ary 2

这里有两件事你需要理解:

1. 模块缓存

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

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

2. 参考文献

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

from my_lib import my_instance
Run Code Online (Sandbox Code Playgroud)

基本上是

import my_lib
my_instance = my_lib.my_instance
del my_lib
Run Code Online (Sandbox Code Playgroud)

现在,当我们修改 中的这个实例时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()
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

输出(检查对象 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!
Run Code Online (Sandbox Code Playgroud)