How to Link Multiple Classes Together Efficiently

2019-07-06 09:25发布

Background: I have been working on a game in Python, and in order to keep everything clean, organized and in a pythonic way, I have a folder containing multiple python files, each containing one big class, for example "MapEngine" or "NPCEngine".

From main.py, I am loading each class from each file and "glueing everything together with a "Game" class, such as:

from folder import *

class Game:

    def __init__(self):
        self.MapEngine = MapEngine.MapEngine()
        ...

    def loop(self):
        ...

Since classes such as "CollisionEngine" requires data from other classes such as, "MapEngine", I usually assign some variables in the former (i.e. CollisionEngine) to the latter (i.e MapEngine), in order to use MapEngine's loaded map data or functions:

class CollisionEngine:

    def __init__(self, MapClass, ...):
        self.MapEngine = MapClass

Problem: Well, since many classes have to be linked to others, it became hard after a while to figure out which class to load first in order to assign variables. Furthermore, classes like "EventEngine" need to have access to every other class. My code became hard to read, and I have trouble when 2 classes are equally important to each other.

Question: I have heard of class inheritance, but I do not think it can be applied here because each class is very different as in its function. Therefore, is there a way to beautifully link every class together, as if it was all part of one big class? In other words, is there a way to refer to variables from other classes, from within a class?

(My thoughts: Perhaps, I can write a class called "Request", and it will act as a top level class manager. Although, I think I will have to use functions such as exec() or eval(), which are not efficient and are somewhat dangerous.)

This is my first post, I've tried to be as explicit as possible, please ask me for clarification, & thank you for your reply!

标签: python class
2条回答
forever°为你锁心
2楼-- · 2019-07-06 09:36

Consider separating your project into layers - that should help you keep things more organised and make the imports more natural.

The principle is that lower layers of your code "cake" shouldn't depend on (read: import) upper layers of your code.

For example you might have a foundation layer which contains common data structures, util classes and algorithms that are used in lots of your code at various layers.

Then you might have a model layer which depends on the foundation layer (i.e. data structures/utils/algorithms) but nothing else. The model layer provides models of objects within the domain.

You might then have a game layer which depends on the model layer (so it would be quite reasonable for modules in your game layer to import things from the model layer, but not vice versa).

查看更多
可以哭但决不认输i
3楼-- · 2019-07-06 09:37

Well, after many tries, I have figured out a (sketchy) way of solving my problem. Of course, as eddiewould suggested, I will have a better organization and multiple layers for my code, but if one would like to have multiple classes all linked together, simply include a variable to the main class (that called every class) to every class. I believe that a code snippet will explain it better:

main.py
engine_folder
----> engine_1.py
----> engine_2.py

in main.py, engine_1 and engine_2 are loaded:

from engine_folder import engine_1, engine_2

class game:

  def __init__(self):
      self.engine_1 = engine_1.engine(self, ...)
      self.engine_2 = engine_2.engine(self, ...)
      #where engine_1.engine and engine_2.engine are
      #two classes that need to transfer data between
      #each other

  def run(self):
      self.engine_1.run()
      self.engine_2.run()

Notice how engine_1.engine's first argument is self, which refers to the top level class which called this class. Now, in engine_1, if we would want to print a variable from engine_2, the class would look similar to this:

class engine:

  def __init__(self, top_level_class, ...):
      self.top_level_class = top_level_class

  def run(self):
      print self.top_level_class.engine_2.random_var

This is very beautiful (besides the fact that print self.top_level_class.engine_2.random_var is very long), but compared to something like:

class EventEngine:

  def __init__(self, Camera_Class, Map_Class, Character_Class, Skill_Class,
               Interface_Class, Sprite_Class, Dialog_Class, Game_Class,
               Item_Class):
      self.ItemEngine = Item_Class
      self.GameEngine = Game_Class
      self.DialogEngine = Dialog_Class
      self.SpriteEngine = Sprite_Class
      self.SkillEngine = Skill_Class
      self.CameraEngine = Camera_Class
      self.MapEngine = Map_Class
      self.CharacterEngine = Character_Class
      self.IEngine = Interface_Class

The new version:

class EventEngine:
  def __init__(self, top_level_class):
      self.top = top_level_class
      #a var from Map_Class can be called as such:
      #self.top.MapEngine.map[0][1]
      #and I can call variables from every class, not only those I 
      #have loaded like before

is much better and much cleaner.

查看更多
登录 后发表回答