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”中需要唯一实例时将其实例化,但是我发布此问题的主要原因是为了解决问题这个特定的概念。
这里有两件事你需要理解:
Python 缓存模块导入以提高性能,即使您这样做,也会发生这种情况from foo import bar。模块对象存储在sys.modules.
因此,在您的情况下,file_a和file_b都访问相同的模块对象my_lib和相同的实例my_instance。
在 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_a并file_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)