1

I have been experimenting with the idea of function classes as explained in this article and Composition applied to function dependencies as described in the following questions:

Consider the following mathematical functions, where x is a variable and a, b and c are constants:

f(x) = a*x**2+b*x+c
g(x) = a*sin(3*x)

As python function classes these can be expressed as follows:

import numpy as np

class F:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
    def __call__(self, x):
        return self.a*x**2+self.b*x+self.c

class G:
    def __init__(self, a):
        self.a = a
    def __call__(self, x):
        return self.a*np.sin(3*x)

For several reasons which I prefer not to elaborate here, I prefer to have one meta class which can be instantiated and assigned any function. The difficulty is of course the constants as self is undefined outside of a class. Here's what I mean:

def f(x):
    return a*x**2+b*x+c

F = FunctionClass(f)
#how to make a, b and c instance variables?

If I don't do this I am condemned to writing a class for every function, which defeats the purpose of what I am trying to achieve. I've asked a question addressing this on a more technical level in stack over flow but it was not very popular at all

Is there a design pattern or python construct that can allow me to achieve this? Perhaps decorators? Perhaps use of the __dict__ attribute? Any ideas?

user32882
  • 267
  • @Asadefa What do you mean "Don't use python"? – Filip Milovanović Mar 16 '20 at 21:18
  • @user32882, I am smelling a possible XY-problem here. Even though you said you rather don't elaborate, can you tell us what you are trying to achieve with your single meta class? – Bart van Ingen Schenau Mar 17 '20 at 07:45
  • I am trying to define a metaclass which would enable a user with limited OOP knowledge to use and implement the parametric functionality allowed by a metaclass. I would like the user to define a function as they would regularly and pass it to this metaclass. – user32882 Mar 17 '20 at 08:37
  • Aside: You example F and G are not unary function objects, they are nullary function objects. You probably meant def __call__(self, x): – Caleth Mar 17 '20 at 08:59
  • @Caleth yes you are correct. I made the correction in the original question. A good example of why you should run your code before posting on here! – user32882 Mar 17 '20 at 10:14
  • 1
    To attempt to assist in illustrating the question, the general problem is of managing functions which apply a complex calculation and would have a large number of parameters as part of that calculation. The problem is presented from a physics context, where common formulas can be complex and incorporate a lot of physical "constants" (that is, empirically defined values). The author wishes to make a distinction between parameters which he considers true variables, and these defined values which, ideally, he will not have to individually provide on each and every call of the function. – Steve Mar 17 '20 at 10:32
  • 1
    ...and additionally, the author does not want to employ programmatic constants or global variables. Instead, he wants at some level to define the core function in a pure fashion - providing all dependencies and defined values as parameters, along with providing what we'd more naturally think of as the variables - and thus retain the flexibility potentially to adjust or use a different set of defined values within the same program. Ultimately, he wants some happy medium between stating every parameter at the site of every call, and on the other hand not being able to adjust the defined values. – Steve Mar 17 '20 at 10:37
  • Would something like this be a good starting point for what you are trying to achieve? You can also combine it with my answer below if you don't want to hardcode the parameters (or make use of functools.partial - referenced in the answer by Caleth). – Filip Milovanović Mar 17 '20 at 19:03