Reputation: 3782
I am hoping to get a good way to make passing arguments to any function easy. I am making a huge amount of functions with a ton of variables taken for each one. Each function calls a lot of functions underneath them, which use some of the same parameters.
I have decided that I can create a structure that will contain default parameters for these functions and then the user may set them to be constant at a value they decide or allowed to vary as a fitting procedure is performed - however, a default value is given up-front for each parameter.
I have been thinking of the best way to do this with the functions which would be for any function f()
called to take any amount of relevant parameters; so f()
will return the same as f(default_param_structure)
, as the defaults are assumed. In addition, calling f(arg1=1, arg31='a')
will replace the relevant parameters.
Here is an example I am trying to work out:
import pandas as pd
import numpy as np
default_a = 1
default_a_min = 0
default_a_max = 2
default_b = 2
default_b_min = 1
default_b_max = 3
def default_param_struct():
a = np.array([default_a, default_a_min, default_a_max])
b = np.array([default_b, default_b_min, default_b_max])
d = {'a': a, 'b': b}
return pd.DataFrame(d, index=['val', 'min','max'])
def f(a=default_a, b=default_b, *args, **kwargs):
return kwargs
default_param_df = default_param_struct()
print default_param_df
def_param_dict = default_param_df.loc['val'].to_dict()
print def_param_dict
# This should print {'a': 3, 'b': 2} (i.e. a is passed and default_b is given automatically)
print f({'a':3})
# This should print {'a': 1, 'b': 2} (as this is the default parameter structure calculated in the function)
print f(def_param_dict)
# This should print {'a': 1, 'b': 2} (default parameter structure is assumed)
print f()
# This should print {'a': 4, 'b': 2} (i.e. a is passed and default_b is given automatically)
print f(a=4)
# This should print {'a': 3, 'b': 5} as they are both passed
print f(a=3, b=5)
But the output is:
a b
val 1 2
min 0 1
max 2 3
{'a': 1, 'b': 2}
{}
{}
{}
{}
So none of the arguments are making it in. Does anyone know how to solve this? Is there a more elegant solution?
Upvotes: 2
Views: 66
Reputation: 180421
You are using passing a
and b
which are the first args a=default_a, b=default_b
so you are passing no kwargs, unless you pass different names you are not going to see any output for kwargs:
print f(f=3, j=5)
{'j': 5, 'f': 3}
Check if a and b are passed as kwargs if you want default values, setting the value to some default if the values are not passed in:
def f(*args, **kwargs):
a,b = kwargs.get("a","default_value"),kwargs.get("b","default_value")
You should add a docstring explaining the usage.
Upvotes: 1
Reputation: 76297
You write
I am making a huge amount of functions with a ton of variables taken for each one.
There are technical solutions for this, but this is usually an indication of some design flaw.
E.g., if you have functions calling each other, passing the same huge number of arguments over and over, then perhaps they should be methods of a class, and most of the arguments should be members. This will both increase encapsulation as well as decrease the number of arguments passed (the arguments are implicit in self
).
Otherwise, you might consider making your parameters themselves an OO hierarchy. Perhaps you might need some class describing parameters; perhaps it needs to be subclassed, etc.
IMHO, you shouldn't be solving this with technical tricks.
Upvotes: 5