2013-06-02 62 views
1

我在单个文件中构建了一个相当大的程序。该文件的大小使其无法工作,所以我决定分割成多个模块,但此后对可变范围产生了很大的困扰。我已经在很大程度上修正了它(一路上有相当一段时间的学习),但我很想理解好的结构,以避免以后的经验教训艰难。有几个具体的要点,但一般的建议也是受欢迎的。什么是构建多模块python程序的最pythonic方法?

模块需要共享同一个命名空间

我,似乎需要共享同一个命名空间两个模块。一个是程序的主要流程(向对象传输数据和调用UI),另一个是UI(它响应用户输入,调用主流)。

这些模块中的每一个都应该导入另一个,然后主文件同时导入?这对我来说并不特别优雅。

从[MODULENAME]进口*

在这个问题的答案:

Python: Sharing global variables between modules and classes therein

有是from [modulename] import *应该避免的建议。

可以使用from [modulename] import *来构建一个只有类定义的模块吗?什么是“安全”用例?

+0

为什么你认为你的两个模块需要共享相同的命名空间? – BrenBarn

+0

@BrenBarn所以他们可以互相打电话。程序流程功能对数据做了一些处理,这些数据决定了需要呈现给用户的内容,因此它调用了UI。然后,用户界面接受用户的响应,并需要调用程序流程功能来做一些分析/决策。 – user1379351

+0

循环依赖不能在python中工作。当module_a导入module_b时,python没有经过“import module_b”语句解释module_a。这意味着您将在module_a中导入后遇到名称错误。这听起来像你应该坚持一个大文件,或花一些时间重新设计,所以你可以分解出不依赖于任何东西的模块。 – Seth

回答

1

需要访问对方名称空间的模块与需要共享相同名称空间的模块不同。我想不出from modulename import *你可以做什么,你不能用import modulename做什么。你只需要在modulename.前面加上你的名字,这是件好事,而不是坏事。它使您的代码自行记录,这就是为什么要避免from modulename import *

您可以让UI和主流程模块相互导入。遇到问题的唯一方法是如果您在函数范围之外引用它们之间的名称。例如

# mainflow.py 
import ui # interpreter stops reading mainflow and starts reading ui 

class Foo: 
    ... 

theUI = ui.UI() 

# ui.py 
import mainflow # mainflow already being loaded; interpretation of ui continues uninterrupted 

def dosomething(): 
    myfoo = mainflow.Foo() # so far so good, not interpreted until the function is called 

class Bar(mainflow.Foo): # mainflow.Foo not reached yet, error here 
    ... 

class UI: 
    ... 

在另一方面,如果UI偶然得到先进口,然后你在theUI = ui.UI()得到错误,当所有mainflow得到了诠释,但UI只被远解释作为import mainflow。但是,只要你把所有的引用都放在函数中,你就可以相处得很好。例如。

# mainflow.py 
import ui 
... 

theUI = None 

def initialize(): 
    global theUI 
    theUI = ui.UI() 

这些类之间的依赖依然存在问题;我建议你不要做那样的事情。但是,如果你做了,你可以让整个事情的工作,这种奇怪的做法:

# mainflow.py 
... 

theUI = None 

def initialize(): 
    global theUI 
    theUI = ui.UI() 

import ui # Waht!? Crazy! Import at the bottom of a file. Now all of mainflow's names are guaranteed to exist and ui can access them. 

现在用ui.py的第一个版本,并mainflow.py的最后一个版本,该计划将编译和运行。我不真的推荐以上;更好地组织你的代码,所以你没有这种依赖关系。但是,如果你所拥有的只是在模块中的函数之间来回调用,则不必诉诸于这些技巧。

还有更多面向对象的设计方法可以让你的UI和你的程序流程不直接相互依赖,但是这样的重新设计会涉及更多的复制和粘贴到文件和前缀名称module.我不'除非你有特定的原因,否则你认为你不想过分重新设计。

+0

虽然我同意你说的大部分内容,但最后一部分的代码存在错误。如果在'initialize()'函数中有全局的''''''语句,那么不需要'theUI = None'。 – martineau

+0

如果你有任何可以在'initialize'之前运行的代码,这可能是可取的。然后它可以检查用户界面是否已经初始化。 – morningstar

+0

啊,是的,使用全局变量的乐趣...... – martineau

相关问题