From time to time I face this dilemma. Suppose I have a function like this:
def foo(..., **kwargs):
...
actor = make_actor(..., **a_kwargs)
return actor.act(..., **b_kwargs)
I want to let the caller specify kwargs to pass to make_actor()
(a_kwargs), and to act()
(b_kwargs). The problem is, of course, that foo
can only take **kwargs
once.
(In almost all cases a_kwargs and b_kwargs share no common keys, so we don't need to worry about param-name clashes).
I can think of several approaches, each with its own clear disadvantages/limitations.
def foo1(..., **kwargs):
...
a_kwargs = {k:kwargs.pop(k) for k in kwargs.keys() if k in ['arg1','arg2',...]}
actor = make_actor(..., **a_kwargs)
return actor.act(..., **kwargs)
def foo2(..., arg1=DEFAULT1, arg2=DEFAULT2, ..., **b_kwargs):
...
actor = make_actor(..., arg1=arg1, arg2=arg2, ...)
return actor.act(..., **b_kwargs)
def foo3(..., a_kwargs={}, **b_kwargs):
...
actor = make_actor(..., **a_kwargs)
return actor.act(..., **b_kwargs)
def foo4(..., a_kwargs={}, b_kwargs={}):
...
actor = make_actor(..., **a_kwargs)
return actor.act(..., **b_kwargs)
Which is the most pythonic? Is there another approach I overlooked which is superior to the four above?
In the general case we might want to split kwargs for passing to more than two other functions.
In general, the fourth option makes the most sense.
Even though it compromises on the ability to use kwargs
in your main function, it makes the code clear, allows for future changes and reduces excessive listing of arguments. It also doesn't mean you have both an excessive list of kwargs
and a dictionary going into the same function, which seems inconsistent.
Simple is better than complex
, Readability counts
, practicality beats purity
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With