0

It seems like there should be a simple answer to this but I'm not finding it. I have a set of equations with two or three variables of interest (say, x, y, and z) and a whole bunch of parameters (a,b,c, . . . z) that are used for calibrating the model that the equations represent. I am able write down functions with the form "def func(variables, parameters): return stuff", and do what I want with them, which is solving for say, x given y and z for a given choice of parameters. I also need to be able to change the parameters as the model calibration changes and also test how the model output changes over a range of parameters. One other piece of info, which is that I need to use something like fsolve to find where the equations intersect to solve the model.

This works fine but is impossible to read, because each function has a super-long list of inputs. I want the code to be understandable to others. Is there a way to have the function read a sequence of parameters so that the functions take the form func(x,y,z, params)?

6
  • 1
    This is quite broad. But yes, parameters can expect to receive a container of sorts. A dict, namedtuple, list, etc etc Commented Dec 31, 2018 at 22:03
  • That works if I make params a list and call them in the function by their index (params[0], etc). But this too is unreadable. I want to be able to use the variable names in the model (i.e., the first parameter is alpha, the second is beta, etc, and the formula uses alpha and beta). Easy way to do that? Commented Dec 31, 2018 at 23:02
  • Have you read about *args and **kwargs? docs.python.org/2/tutorial/… Commented Dec 31, 2018 at 23:43
  • Then use a namedtuple or even just unpack your list or use a parameter object with the names as attributes Commented Dec 31, 2018 at 23:49
  • (responding to Liam) Tried. I probably am not fully getting how that works, but it seems work fine for calling the function. That is, if I define my function as def myfunc(x,y,z,a,b,...z) then using the * and ** work great for calling it. But (and this is really just the short version of my question above), how do I use * an ** for defining it so that I can, in the expressions refer to a, b . . . z? Commented Dec 31, 2018 at 23:51

1 Answer 1

1

one easy way to simplify your calls would be to use simple objects and set attributes on it.

class Params:
    pass

p = Params()
p.a = 'some value'
    ...
p.q = 'some other value'

You can then define your function using

def myfunc(x, y, z, params):
    ....
    something = x+y+z+params.q

You would call the function like

result = myfunc(1.2, 3.4, 5.6, p)

This will allow you to access the individual parameters as attributes of the params parameter, making the calls clearer.

Sign up to request clarification or add additional context in comments.

3 Comments

Definitely works. Was hoping for something even simpler but that does the job. Thx.
You could replace the simple class with a bunch, allowing you to set attribute values at the same time as creating the Params object.
Nice. Thanks. I hadn't seen Bunch before.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.