views:

57

answers:

2

I have several layers of function calls, passing around a common dictionary of key word arguments:

def func1(**qwargs):
    func2(**qwargs)
    func3(**qwargs)

I would like to supply some default arguments in some of the subsequent function calls, something like this:

def func1(**qwargs):
    func2(arg = qwargs.get("arg", default), **qwargs)
    func3(**qwargs)

The problem with this approach is that if arg is inside qwargs, a TypeError is raised with "got multiple values for keyword argument".

I don't want to set qwargs["arg"] to default, because then func3 gets this argument without warrant. I could make a copy.copy of the qwargs and set "arg" in the copy, but qwargs could have large data structures in it and I don't want to copy them (maybe copy.copy wouldn't, only copy.deepcopy?).

What's the pythonic thing to do here?

+2  A: 

Just build and use another dict for the purpose of calling func2, leaving the original alone for the later call to func3:

def func1(**qwargs):
    d = dict(arg=default)
    d.update(qwqargs)
    func2(**d)
    func3(**qwargs)

This is if you want a setting for arg in qwargs to override the default. Otherwise (if you want default to override any possible setting for arg in qwargs):

def func1(**qwargs):
    d = dict(qwargs, arg=default)
    func2(**d)
    func3(**qwargs)

since the keyword-argument to dict overrides the value in the positional argument, if any.

Alex Martelli
A: 

To create a new dict with the same keys and values you can use

 newdict=dict(qwargs)

If qwargs doesn't contain really many keys that's cheap.

If it's possible you could rewrite the functions to take their args really as dict instead of multiple args.

Florian Diesch