我最近被告知我应该将我的代码保存在单独的文件中;例如main.py
,engine.py
,settings.py
等。虽然这肯定会带来诸多好处,比如更容易管理,可扩展性等等,但对我来说似乎有太多缺点......
例如,如果我有一个名为settings.py
的脚本,其中定义了屏幕对象的大小,模拟的速度和各种对象的颜色,如果需要这些变量,我该怎么办?我的engine.py
脚本和我的main.py
脚本?我在两个脚本中都导入了两次吗?看起来相当混乱。如果engine.py
脚本中的某些类需要main.py
的代码,该怎么办?
让我告诉你具体情况......
我的main.py
脚本本身导入Pygame,初始化它,依此类推。它曾经有一个表示屏幕上对象的类,该类有一个方法draw
,它只是调用Pygame绘制函数。现在,当我把这个类放在我的engine.py
脚本中时,事情就不再有效了,因为Pygame在那里不存在!我最终在settings.py
中导入engine.py
和Pygame,然后将引擎导入main.py
,但是它更像是初始化程序而不是引擎......有没有办法处理像这样的事情,如一般指导线?
答案 0 :(得分:3)
以下是导入的官方PEP指南:http://www.python.org/dev/peps/pep-0008/#imports
另请参阅此StackOverflow问题:What are good rules of thumb for Python imports?
您可以从多个类中导入变量而不会出现问题,但您应该尝试构建代码,以便不循环导入内容。 Circular import dependency in Python
答案 1 :(得分:1)
你应该看看这个模型,这可能有助于你理解事物。 我认为这是最适合你想做的事情
这里还有一些文档: http://www.wkoorts.com/wkblog/2007/12/23/mvc-design-patterns-with-python-links/
在这种情况下,进口看起来应该是合乎逻辑且必要的。 我想补充一点,就是你已经对你的3个文件做了大致的事情。
答案 2 :(得分:1)
不是答案,但是:
settings.py
应该是settings.ini
,您应该使用ConfigParser
阅读它。阅读配置文件一次,并在模块之间共享结果ConfigParser.RawConfigParser
。
答案 3 :(得分:1)
其他语言(尤其是Java,其中编译器几乎强制要求)的常见做法是每个类有一个文件。
至于你提到的文件间依赖关系,你应该考虑避免使用全局变量。
这是另一个更好地回答你问题的相关问题。
答案 4 :(得分:1)
将模块导入多个其他模块并不麻烦。与具有数千行代码的模块相比,它更清晰。
循环导入确实存在问题。但是你的情况听起来并不像循环导入问题。你说“现在,当我把这个类放在我的engine.py脚本中时,事情就不再起作用了,因为Pygame在那里不存在!我最终在engine.py中导入settings.py和Pygame,然后导入引擎进入main.py“。
为什么不能将课程放在engine.py
中,然后将其导入main.py
?一个非常简单的方法是将回调传递给你的类:
# 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
,可以在必要时调用它来获取可绘制数据,另一个外部绘图函数可以调用它。
另一种方法是为Pygame创建一个完全独立的模块。我对Pygame知之甚少,所以有可能这不起作用,但是说你有一个处理Pygame初始化和状态的模块。您可以在main
中将其初始化一次,然后将其导入到您想要的任何位置。
答案 5 :(得分:0)
您可以在settings.py中的任何需要的模块中导入符号。这就是概念。实际问题是当您进行循环导入时。例如如果engine.py
中需要main.py
内的符号,反之亦然,该怎么办?在这种情况下,一个常见的模式是在第三个模块中打破这些依赖关系,main.py
和engine.py
可以从中导入,而没有任何问题。