简体   繁体   English

构造多模块python程序的最pythonic方法是什么?

[英]What is the most pythonic way to structure a multi-module python program?

I've built a fairly sizeable program in a single file. 我已经在单个文件中构建了一个相当大的程序。 The size of the file was making it unworkable, so I decided to split into multiple modules, but have since had a major headache of variable scope. 该文件的大小使其无法使用,因此我决定拆分为多个模块,但是此后一直困扰着可变范围。 I've largely fixed it (with a fair bit of learning along the way), but I'm keen to understand good structuring to avoid future lessons learnt the hard way. 我已经对其进行了很大程度的修复(在此过程中需要大量学习),但是我渴望了解良好的结构,以避免将来通过艰辛的课程学习。 There are a couple of specific points, but general advice is also welcome. 有几点要点,但也欢迎提供一般性建议。

Modules that need to share the same namespace 需要共享相同名称空间的模块

I have two modules that seem to need to share the same namespace. 我有两个似乎需要共享相同名称空间的模块。 One is the main flow of the program (which transfers data to and from objects, and calls the UI), the other is the UI (which responds to user input, calling the main flow). 一个是程序的主要流程(用于与对象之间的数据传输,并调用UI),另一个是UI(其响应用户输入,称为主要流程)。

Should each of these modules import the other, and then the main file import both? 这些模块中的每个模块都应该导入另一个模块,然后主文件同时导入两个模块吗? That doesn't seem particularly elegant to me. 在我看来,这并不是特别优雅。

from [modulename] import * 从[modulename]导入*

In the answers to this question: 在此问题的答案中:

Python: Sharing global variables between modules and classes therein Python:在其中的模块和类之间共享全局变量

There is a suggestion that from [modulename] import * should be avoided. 有建议,应避免from [modulename] import *

Is it OK to use from [modulename] import * to build together a load of modules that just have class definitions? 是否可以使用from [modulename] import *来构建仅具有类定义的模块负载? What are "safe" use cases? 什么是“安全”用例?

Modules that need to access each other's namespace is not the same as modules that need to share the same namespace. 需要访问彼此名称空间的模块与需要共享相同名称空间的模块不同。 I can't think of anything you can do with from modulename import * that you can't do with import modulename . 我想不出任何东西,你可以用做from modulename import * ,你不能用做import modulename You just have to preface a lot of your names with modulename. 您只需要在许多名称前加上modulename. That's a good thing, not a bad thing. 那是好事,不是坏事。 It makes your code self-documenting, which is why from modulename import * is to be avoided. 它使您的代码可以自我记录,这就是为什么要避免from modulename import *原因。

You can have the UI and main flow modules import each other. 您可以使UI和主流模块相互导入。 The only way you'll run into problems is if you reference names between them outside of the scope of functions. 遇到问题的唯一方法是在函数范围之外引用它们之间的名称。 For example 例如

# 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:
    ...

On the other hand if ui happens to get imported first, then you get the error at theUI = ui.UI() , when all of mainflow has been interpreted but ui has only been interpreted as far as import mainflow . 另一方面,如果ui碰巧先被导入,那么当所有主流都已被解释但ui仅被解释为import mainflow时,您将在theUI = ui.UI()处得到错误。 As long as you put all the references to each other inside functions, though, you can get along fine. 但是,只要将所有引用相互放在函数内部,就可以相处得很好。 Eg 例如

# mainflow.py
import ui
...

theUI = None

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

There's still a problem with the dependency between the classes; 类之间的依赖关系仍然存在问题。 I recommend you don't do anything like that. 我建议您不要那样做。 But if you did, you could make the whole thing work with this strange approach: 但是,如果您这样做了,则可以使用这种奇怪的方法使整个工作正常进行:

# 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.

Now with the first version of ui.py and the last version of mainflow.py, the program would compile and run. 现在有了ui.py的第一个版本和mainflow.py的最后一个版本,该程序将编译并运行。 I don't really recommend the above; 我真的不推荐上述内容; better organize your code so you don't have such dependencies. 更好地组织您的代码,以便您没有此类依赖项。 But if all you have is calls back and forth between functions in modules, you don't have to resort to such tricks. 但是,如果您只是在模块中的函数之间来回调用,则不必诉诸此类技巧。

There are more object-oriented designy ways to make your UI and your program flow not directly depend on each other, but such a redesign would be more involved than just copy and paste to files and prefacing names with module. 还有更多面向对象的设计方法,可以使UI和程序流不直接相互依赖,但是这样的重新设计将涉及更多的工作,而不仅仅是将其复制和粘贴到文件中以及使用module.作为前缀module. I don't think you want to go overboard with your redesign unless you have a specific reason. 除非有特定原因,否则我认为您不希望过度设计。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在python中导入模块的最pythonic方法是什么 - What is the most pythonic way to import modules in python 多模块程序的日志记录 - logging for multi-module program 在我的Python乌龟绘图程序中实现重做的最pythonic方法? - Most pythonic way to implement redoing in my Python turtle drawing program? Python 2:使用字符串解释进行枚举的最优雅/ pythonic方式是什么? - Python 2: What is the most elegant/pythonic way of doing a enum with string interpretations? 什么是setattr()用于模块的pythonic方法? - What is the pythonic way to setattr() for a module? 将JSON字段复制到另一个JSON结构的最pythonic方法是什么? - What's the most pythonic way to copy JSON fields to another JSON structure? 遍历一长串字符串并从原始列表构建新列表的最pythonic 方法是什么? - What is the most pythonic way to iterate through a long list of strings and structure new lists from that original list? 使用循环导入的Pythonic方法来构建模块API - Pythonic Way to structure module API with circular import 确定字节序的最Pythonic方法是什么? - What's the most Pythonic way of determining endianness? 处理标准输入的最Python方式是什么? - What is the most Pythonic way of handling standard input?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM