简体   繁体   中英

How to organize my Python code into multiple classes?

I was recently told that I should keep my code in separate files; like main.py , engine.py , settings.py and so on. Although this surely does have benefits, like easier management, scalability and others, to me it seems like it has too many drawbacks...

For example, if I have a script called settings.py , where some things like sizes of onscreen objects, speed of the simulation and color of various objects are defined, what do I do if those variables are needed both in my engine.py script and my main.py script? Do I import it two times, in both scripts? It seems rather messy. What if some of my classes, that are in the engine.py script, require code from main.py ?

Let me show you the exact situation...

My main.py script imports Pygame in itself, initializes it, and so on. It used to have a class which represented an onscreen object, and that class had a method draw , which just called a Pygame draw function. Now, when I put the class inside my engine.py script, things no longer work, because Pygame doesn't exist there! I ended up importing both settings.py and Pygame in the engine.py , and then importing the engine into main.py , but then it's more like an initializer than an engine... Is there a way to deal with things like these, like general guide lines?

Here are the official PEP guidelines for imports: http://www.python.org/dev/peps/pep-0008/#imports

Also please see this StackOverflow question: What are good rules of thumb for Python imports?

You can import a variable from more than one class without a problem but you should try and structure your code so that things aren't circularly imported. Circular import dependency in Python

You should have a look at this model, which might help you understand things. I think this is the one that would actually fit best with what you want to do

Model-View-Controller

Some more doc here : http://www.wkoorts.com/wkblog/2007/12/23/mvc-design-patterns-with-python-links/

In this case, the imports should seem rather logical and necessary. And I would add that is is roughly what you already do with your 3 files.

Not an answer, but:

settings.py should really be settings.ini , and you should read it using ConfigParser . Read the config file once and share the resulting ConfigParser.RawConfigParser around between modules.

Its common practice in other languages (especially Java, where its practically forced by the compiler) to have one file per class.

As for the inter-file dependencies you mention, you should consider avoiding global variables.

Here's another related question that better answers your question.

How many Python classes should I put in one file?

Importing a module into multiple other modules isn't messy. It's much cleaner than a module with many thousands of lines of code.

It's true that circular imports are problematic. But your situation doesn't sound like there's going to be a circular import problem. You say that "Now, when I put the class inside my engine.py script, things no longer work, because Pygame doesn't exist there! I ended up importing both settings.py and Pygame in the engine.py, and then importing the engine into main.py".

Why can't you just put the class in engine.py and then import it into main.py ? One very simple way to do this would be to pass a callback to your class:

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

What's nice about this approach is that the object is really only responsible for one thing: its own state. Indeed, it might make more sense for this object to not have a draw method at all; or it could have a draw_hook that would be called to get drawable data from it whenever necessary, and another external draw function could call it.

Yet another approach would be to have a completely separate module for Pygame. I don't know much about Pygame, so it's possible this won't work, but say you have a module that handles Pygame initialization and state. You can initialize it once, in main , and import it wherever you want.

You can import symbols from settings.py in any module they are needed. That's the concept. An actual problem is when you have circular imports. eg What if you had some symbols inside engine.py that were needed in main.py and vice versa. In that situation a common pattern is to break these dependencies in a third module, where main.py and engine.py could import from, without any problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM