Home > Net >  Creating default parameters from a variable
Creating default parameters from a variable

Time:05-19

I have many different methods all in different classes with different function signatures that all have the same set of default parameters but usually have different non-default parameters. I wanted to make my code more loosely coupled by having these default parameters reference a variable instead of being hardcoded in each signature so in the case I wanted to change one of the defaults I wouldn't have to visit each method. For example, say I have a dictionary containing {'param1': True, 'param2': False, 'param3': 100} I would want to make each pair act as a default parameter. In theory, it would look something like this:

#So this
defaultParams = {'param1': True, 'param2': False, 'param3': 100}
def func(*args, **defaultParams) #thinking that you could 'spread' the default params into the function based off the var. Obv wouldn't work but that's the functionality I would want

#would be equivalent to this
def func(*args, param1=True, param2=False, param3=100)

#but would NOT look like this as I don't want to have to lookup an item to reference it:
def func(*args, kwargs=defaultParams)

Im wondering if this is possible in python and if it isn't if there is a design pattern that would accommodate this problem.

Thanks

CodePudding user response:

You can't do this in the parameter list, but you can merge with the defaults inside the function.

defaultParams = {'param1': True, 'param2': False, 'param3': 100}

def func(**kwargs):
    kwargs = defaultParams | kwargs

CodePudding user response:

You could do this inside each function in question by doing dictionary updates:

def func(*args, **kwargs):
  kw = dict(defaultParams) | kwargs
  # ... proceed with computation

If you wanted to do this on many functions, you could potentially use a decorator:

def with_defaults(f):
  def wrapper(*args, **kwargs):
    kw = dict(defaultParams) | kwargs
    return f(*args, **kw)
  return wrapper

@with_defaults
def func(*args):
  # ...

I also feel like it's worth pointing out that this sort of pattern can be quite risky, given that dictionaries in Python are mutable -- if something changed defaultParams somewhere, then suddenly the behaviors of all your functions would change. You might mitigate this by making defaultParams a tuple of key-value ordered pairs. (Or, as others have suggested, using a dataclass, but I'm not sure if you'd then lose the dictionary update semantics.)

In addition, the signature information of the functions in question would be off. Probably there's a way to address this using some metaprogramming magic, but it would start to get complex quickly.

  • Related