choosing between Modules and Classes

2020-05-18 20:27发布

问题:

In my application I have to maintain some global application state and global application wide methods like currently connected users, total number of answers, create an application config file etc. There are two options:

  1. Make a separate appstate.py file with global variables with functions over them. It looks fine initially but it seems that I am missing something in clarity of my code.

  2. Create a class AppState with class functions in a appstate.py file, all other modules have been defined by their specific jobs. This looks fine. But now I have to write longer line like appstate.AppState.get_user_list(). Moreover, the methods are not so much related to each other. I can create separate classes but that would be too many classes.

EDIT: If I use classes I will be using classmethods. I don't think there is a need to instantiate the class to an object.

回答1:

The second approach seems better. I'd use the first one only for configuration files or something.

Anyway, to avoid the problem you could always:

from myapp.appstate import AppState

That way you don't have to write the long line anymore.



回答2:

Sounds like the classic conundrum :-).

In Python, there's nothing dirty or shameful about choosing to use a module if that's the best approach. After all, modules, functions, and the like are, in fact, first-class citizens in the language, and offer introspection and properties that many other programming languages offer only by the use of objects.

The way you've described your options, it kinda sounds like you're not too crazy about a class-based approach in this case.

I don't know if you've used the Django framework, but if not, have a look at the documentation on how it handle settings. These are app-wide, they are defined in a module, and they are available globally. The way it parses the options and expose them globally is quite elegant, and you may find such an approach inspiring for your needs.



回答3:

The second approach is only significantly different from the first approach if you have application state stored in an instance of AppState, in which case your complaint doesn't apply. If you're just storing stuff in a class and using static/class methods, your class is no different than a module, and it would be pythonic to instead actually have it as a module.



回答4:

Why not go with an instance of that class? That way you might even be able later on to have 2 different "sessions" running, depending on what instance you use. It might make it more flexible. Maybe add some method get_appstate() to the module so it instanciates the class once. Later on if you might want several instances you can change this method to eventually take a parameter and use some dictionary etc. to store those instances.

You could also use property decorators btw to make things more readable and have the flexibility of storing it how and where you want it stores.

I agree that it would be more pythonic to use the module approach instead of classmethods.

BTW, I am not such a big fan of having things available globally by some "magic". I'd rather use some explicit call to obtain that information. Then I know where things come from and how to debug it when things fail.



回答5:

Consider this example:

configuration
|
+-> graphics
|   |
|   +-> 3D
|   |
|   +-> 2D
|
+-> sound

The real question is: What is the difference between classes and modules in this hierarchy, as it could be represented by both means?

Classes represent types. If you implement your solution with classes instead of modules, you are able to check a graphics object for it's proper type, but write generic graphics functions.

With classes you can generate parametrized values. This means it is possible to initialize differently the sounds class with a constructor, but it is hard to initialize a module with different parameters.

The point is, that you really something different from the modeling standpoint.



回答6:

I would go with the classes route as it will better organize your code. Remember that for readability you can do this:

from appstate import AppSate


回答7:

I'd definitely go for the second option : having already used the first one, I'm now forced to refactor, as my application evolved and have to support more modular constructs, so I now need to handle multiple simulataneous 'configurations'.

The second approach is, IMO, more flexible and future proof. To avoid the longer lines of code, you could use from appstate import AppState instead of just import appstate.