Reputation: 2957
I am working on a project that requires a large database of python objects, each of which has exactly two methods: __init__
and __call__
. The init
defines attributes specific to each object, while the call
method contains the definition of a function parametrized by the attributes. Right now, I am representing this database using a large .py
file that contains all of the objects. For example, first two entries in the file myfuncs.py
are something like
class Alice:
def __init__(self, a=10, b=4):
self.a = a
self.b = b
self.color = "red"
def __call__(self, X):
return X**2 + self.a + self.b
class Timmy:
def __init__(self, h=1):
self.a = a
self.color = "blue"
def __call__(self, X):
return X**4*self.h
I might use these classes in a separate program:
from myfuncs import Alice
model = Alice(a=10)
y = model(15)
print("The value was ", str(y), " and the color is ", model.color)
Notice that the init
method for both objects contains a hard-coded attribute color
and a value that is specific to that object. All objects in the database have this attribute, and currently the only way to associate this attribute with the object is through a hard-coded value in the constructor.
Rather than having one long .py
file with a bunch of objects (and a lot of boilerplate code), it seems to me like there should be some way to define a database of objects, each with an attribute color
and another attribute function
that contains the contents of the __call__()
method and default keyword arguments. However, after importing a specific object I need it to be treated like a native Python function, and so I'm not sure that storing the functions as strings and then using exec
will work.
While my minimal example may seem contrived, in my application these objects contain in their call
methods complex mathematical formula written as Python functions, the keyword args are the parameter values in these formulae, and the property color
is a label associated with each formula that denotes its symmetry group (which is something I know about each function from external info).
What is the best way to structure my project?
Upvotes: 0
Views: 151
Reputation: 678
Okay, here's a slightly better way that gets rid of a lot of boilerplate:
from abc import abstractmethod, ABC
class BaseModel(ABC):
color: str
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
@abstractmethod
def __call__(self, x):
...
class Alice(BaseModel):
color = 'red'
b = 4
def __call__(self, x):
return x ** 2 + self.a + self.b
class Timmy(BaseModel):
color = 'blue'
h = 1
def __call__(self, x):
return x ** 4 * self.h
This way you only need to define the parts that change from class to class.
Also you can express your print like this:
print(f"The value was {y} and the color is {model.color}")
Upvotes: 1