Reputation: 29
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?
Upvotes: 2
Views: 102
Reputation: 20718
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 @classmethod
s for the different model functions would be fine for me too.
Upvotes: 2
Reputation: 31250
I'm not sure I'm understanding your problem correctly, but I think what I would do is:
1) Make m and k parameters of V
def V(x, m, k):
return -m*x**2 + k*x**4
2) The moment you want to minimize V regarding x, for a fixed m and k, create a partial function that has m and k already set, and minimize that:
from functools import partial
for i in range(5):
m = random.randint(0, 10)
k = random.randint(0, 10)
V_with_fixed_m_k = partial(V, m=m, k=k)
minimize(V_with_fixed_m_k, 0)
Alternatively, make a function that returns a version of V that uses the right m and k:
def parameterized_V(m, k):
def V(x):
return -m*x**2 + k*x**4
return V
But that's basically a reimplementation of functools.partial only for V.
Upvotes: 2