Search code examples
pythonclassproject-structuring

Python structuring - Do I really need a class?


I have a problem to which the solution seems to be creating a class. However, all the methods in this class would be static, and I would only instantiate the class once, so I wonder if using a class is the right way to go.

More specifically, I want to have a separate module to store some functions and some variables that are essentially the skeleton of the program. These functions and variables depend on some parameters that define my model (and I do not want to pass these parameters as arguments for other reasons that I may specify later if relevant). Ex.:

# my_model.py
def V(x):
   return -m*x**2 + k*x**4

On the other module I do a scan over some values of these parameters "m" and "k", and for each of these values I want to, say, find the minimum of V:

# scan.py
from scipy.optimize import minimize
import random, my_model

for i in range(5):
   m = random.randint(0,10)
   k = random.randint(0,10)
   minimize(my_model.V, 0)

Of course, this won't work, because my_model.V has no clue as to what m and k are. As I said, I thought about creating a class in the my_model file, defining the function V (and others!) inside that class, and instantiate the class in scan.py passing the parameters "m", "k" as arguments. But, as I said, this sounds to me as an overuse of the class feature. For instance, clearly the function V above would be static, and so would happen with ALL other definitions in this class. So is there any other, more proper way of achieving what I want, or am I just "over-reacting" and/or completely misunderstanding the use of classes in Python?


Solution

  • You can use functools.partial:

    # my_model.py
    def V(m, k, x):
       return -m*x**2 + k*x**4
    

    And use it like this:

    # scan.py
    import functools
    from scipy.optimize import minimize
    import random, my_model
    
    for i in range(5):
        m = random.randint(0,10)
        k = random.randint(0,10)
        minimize(functools.partial(my_model.V, m, k), 0)
    

    This is only really meant as an alternative to a class. The tastes differ here, some people suggest that you really should do it that way. Using a class and having @classmethods for the different model functions would be fine for me too.