关于类:如何将我的Python代码组织成多个类?

How to organize my Python code into multiple classes?

最近有人告诉我,我应该将代码保存在单独的文件中,比如main.pyengine.pysettings.py等等。虽然这确实有好处,像更容易管理、可扩展性和其他方面,但对我来说,它似乎有太多的缺点…

例如,如果我有一个名为settings.py的脚本,其中定义了屏幕上对象的大小、模拟速度和各种对象的颜色等内容,那么如果在我的engine.py脚本和我的main.py脚本中都需要这些变量,我该怎么办?在两个脚本中,我导入它两次吗?看起来很乱。如果我的一些类(在engine.py脚本中)需要来自main.py的代码怎么办?

让我告诉你确切的情况…

我的main.py脚本本身导入pygame,初始化它,等等。它以前有一个表示屏幕上对象的类,该类有一个方法draw,它刚刚调用了pygame draw函数。现在,当我把这个类放到我的engine.py脚本中时,事情就不再有效了,因为pygame不存在!我最终在engine.py中导入settings.py和pygame,然后将引擎导入main.py中,但这更像是初始值设定项而不是引擎…有没有办法处理像这样的事情,比如一般的指南?


以下是官方的PEP进口指南:http://www.python.org/dev/peps/pep-0008/imports

另外,请看这个stackoverflow问题:对于python导入,什么是好的经验法则?

您可以从多个类中导入变量,而不会出现问题,但是您应该尝试构造代码,这样就不会循环导入内容。python中的循环导入依赖项


将一个模块导入多个其他模块并不麻烦。它比具有数千行代码的模块更干净。

循环进口确实存在问题。但你的情况听起来不像是循环进口问题。你说"现在,当我把类放在我的engine.py脚本中时,事情就不工作了,因为pygame不存在!我最终在engine.py中导入了settings.py和pygame,然后将引擎导入main.py"。

为什么你不能把这个类放在engine.py中,然后把它导入main.py中呢?一个非常简单的方法是将回调传递给您的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# engine.py
...
class ClassWithDraw(Subclass):
    def __init__(self, draw_callback):
        ...
        self._draw_func = draw_callback
        ...
    def draw(self):
        self._draw_func()

# main.py

from engine import ClassWithDraw
drawer = ClassWithDraw(drawfunc)

这种方法的好处在于,对象实际上只负责一件事:它自己的状态。实际上,对于这个对象来说,根本没有draw方法可能更有意义;或者它可以有一个draw_hook,在必要时调用它以从中获取可提取的数据,而另一个外部的draw函数可以调用它。

另一种方法是为Pygame建立一个完全独立的模块。我对Pygame不太了解,所以这可能不起作用,但假设您有一个模块来处理Pygame初始化和状态。您可以在main中初始化它一次,然后将它导入到您想要的任何地方。


它在其他语言(尤其是Java,在编译器实际强制的情况下)每类有一个文件。

对于您提到的文件间依赖关系,您应该考虑避免使用全局变量。

这是另一个相关问题,可以更好地回答您的问题。

一个文件中应该放多少个Python类?


不是答案,而是:

settings.py应该是settings.ini,你应该用ConfigParser来读。读取配置文件一次,并在模块之间共享生成的ConfigParser.RawConfigParser


您应该看看这个模型,它可能会帮助您理解一些事情。我认为这是最适合你想做的事情

模型视图控制器

这里还有一些医生:http://www.wkoorts.com/wkbog/2007/12/23/mvc-design-patterns-with-python-links/

在这种情况下,进口似乎是相当合乎逻辑和必要的。我想补充一下,这大概就是你已经对3个文件所做的。


您可以从需要的任何模块中的settings.py导入符号。这就是概念。实际的问题是当您有循环导入时。例如,如果在engine.py中有一些在main.py中需要的符号,反之亦然。在这种情况下,一种常见的模式是在第三个模块中打破这些依赖关系,在第三个模块中,main.pyengine.py可以毫无问题地从中导入。