Python名称空间:如何在其他模块中访问唯一的对象?

Python名称空间:如何在其他模块中访问唯一的对象?,python,namespaces,pyqt,Python,Namespaces,Pyqt,我正在写一个中等大小(几个KLOC)的PyQt应用程序。为了便于理解,我一开始是在漂亮的模块中编写的,但现在我对Python名称空间的规则感到迷茫。在某些情况下,只实例化一个类的一个对象作为其他代码的资源是很重要的 例如:表示作为子流程附加的Aspell的对象,提供了一个检查(word)方法。另一个示例:该应用程序具有单个QTextEdit,其他代码需要调用该单一对象的方法,例如“if theEditWidget.document().isEmpty()…” 无论我在哪里实例化这样一个对象,它只

我正在写一个中等大小(几个KLOC)的PyQt应用程序。为了便于理解,我一开始是在漂亮的模块中编写的,但现在我对Python名称空间的规则感到迷茫。在某些情况下,只实例化一个类的一个对象作为其他代码的资源是很重要的

例如:表示作为子流程附加的Aspell的对象,提供了一个检查(word)方法。另一个示例:该应用程序具有单个QTextEdit,其他代码需要调用该单一对象的方法,例如“if theEditWidget.document().isEmpty()…”

无论我在哪里实例化这样一个对象,它只能从该模块中的代码中引用,而不能从其他模块中引用。例如,编辑小部件的代码不能调用Aspell网关对象,除非在同一模块中创建Aspell对象。很好,但其他模块也需要它

在类中提供了,但在我看来,许多对象都有完全相同的问题:它是唯一的对象,只能在创建它的模块中使用。还是我完全错过了这里的船

好的,我在别处建议过,这似乎是我问题的一个简单答案。我刚刚测试了以下内容:

junk_main.py:

import junk_A
singularResource = junk_A.thing()
import junk_B
junk_B.handle = singularResource
print junk_B.look()
垃圾垃圾:

class thing():
    def __init__(self):
        self.member = 99
垃圾桶:

def look():
    return handle.member

当我运行junk_main时,它会打印99。因此,主代码可以通过赋值将名称注入模块中。我在想这是个坏主意的原因。

您可以使用
操作符访问模块中的对象,就像使用函数一样。例如:

# Module a.py
a = 3

>>> import a
>>> print a.a
3
这是一个简单的示例,但您可能希望执行以下操作:

# Module EditWidget.py
theEditWidget = EditWidget()
...

# Another module
import EditWidget

if EditWidget.theEditWidget.document().isEmpty():
或者

如果您确实选择了从导入*路径,您甚至可以在模块中使用希望模块导出到*的所有对象的名称(作为字符串)列表。因此,如果您只想导出编辑小部件,可以执行以下操作:

# Module EditWidget.py
__all__ = ["theEditWidget"]
theEditWidget = EditWidget()
...
在某些情况下,只实例化一个类的一个对象作为其他代码的资源是很重要的

与其尝试创建某种单例工厂,不如在程序的主要入口点和实例化需要它的对象之间的某个地方创建单例对象?一次性使用对象可以作为参数传递给另一个对象。从逻辑上讲,您不会多次创建单一用途对象

例如:

def main(...):
    aspell_instance = ...
    myapp = MyAppClass(aspell_instance)
或者


我不知道这是否足够清楚,或者是否适用于你的情况。但老实说,我唯一一次发现自己做不到这一点的是在基于CherryPy的Web服务器上,那里的入口几乎无处不在。

事实证明,答案比我想象的要简单。正如我在问题中提到的,主模块可以向导入的模块添加名称。任何代码都可以向对象添加成员。因此,创建模块间通信区域的简单方法是主要创建一个非常基本的对象,如IMC(模块间通信器),并将其他模块可用的任何内容分配给它作为成员:

IMC.special = A.thingy()
IMC.important_global_constant = 0x0001
等导入任何模块后,只需为其分配IMC:

import B
B.IMC = IMC

现在,从软件设计的角度来看,这可能不是最好的想法。如果您只是将IMC限制为包含命名常量,它的行为就像一个C头文件。如果只是为了访问单一资源,它就像一个外部链接。但由于Python的自由规则,任何模块中的代码都可以修改或向IMC添加成员。以一种无纪律的方式使用,“谁改变了那个”可能是一个调试问题。如果有多个进程,竞争条件是一种危险。

如果您收到的答案之一解决了您的问题,您能否通过单击复选标记来接受它?如果您得到的答案之一解决了您的问题,请通过单击复选标记来接受它。我的印象是导入也意味着执行,因此,如果在中间的示例中,多个模块导入EditWidget,这是否意味着多个对象实例化?不,只有运行中的第一个导入才会执行代码;同一模块的其他导入只创建对第一个模块的引用。如果您做过任何C/C++编程,通常会放入一些代码以确保您的文件只获得一次
#include
d(相当于导入的C),但Python会自动为您这样做。特别是,
sys.modules
是Python在执行/加载模块后存储模块的字典。一旦存在,后续导入只需在该dict中查找对象。
IMC.special = A.thingy()
IMC.important_global_constant = 0x0001
import B
B.IMC = IMC