A function is simply an object that can be called so defining a class with a __call__ method is in principle equivalent to defining a function. At least in the context you are giving.
So:
def user_func(x, y, z):
return anything_with(x, y, z)
is equivalent to:
class user_class(object):
@staticmethod # staticmethod so that it can be called on the class
def __call__(x, y, z):
return anything_with(x, y, z)
as it stands this is just obfuscation. But the magic happens when you create an instance with predefined attributes and you only specifiy the variable arguments as parameters for the call:
class user_class(object):
def __init__(self, x):
self.x = x
def __call__(self, y, z): # No x as parameter!
return do_anything_with(self.x, y, z) # use the predefined x here
but you need to alter the way you call lib_func then:
x = 0
user_class_instance = user_class(0)
result = lib_func(user_class_instance, param1)
So it will repeat to call the instance with different y and z but x will be kept constant
Most of such lib_func functions however allow passing variable parameters (such that will be given to the user_func), for example scipy.optimize.curve_fit:
curve_fit(user_func, x, y, [initial_guess_param1, param2, ...])
there user_func will be called by curve_fit internally (you don't have to do anything!) like:
user_func(x, initial_guess_param1, param2, ...)
# Then curve-fit modifies initial_guess_param1, param2, ... and calls it again
user_func(x, initial_guess_param1, param2, ...)
# and again modifies these and calls again
user_func(x, initial_guess_param1, param2, ...)
# ... until it finds a solution
there x and y are defined and not changed when calling curve_fit but initial_guess_param1 will be changed while finding the optimal curve_fit
.