What is the proper way to use
**kwargs in Python when it comes to default values?
kwargs returns a dictionary, but what is the best way to set default values, or is there one? Should I just access it as a dictionary? Use get function?
class ExampleClass: def __init__(self, **kwargs): self.val = kwargs['val'] self.val2 = kwargs.get('val2')
A simple question, but one that I can't find good resources on. People do it different ways in code that I've seen and it's hard to know what to use.
You can pass a default value to
get() for keys that are not in the dictionary:
self.val2 = kwargs.get('val2',"default value")
However, if you plan on using a particular argument with a particular default value, why not use named arguments in the first place?
def __init__(self, val2="default value", **kwargs):
While most answers are saying that, e.g.,
def f(**kwargs): foo = kwargs.pop('foo') bar = kwargs.pop('bar') ...etc...
is "the same as"
def f(foo=None, bar=None, **kwargs): ...etc...
this is not true. In the latter case,
f can be called as
f(23, 42), while the former case accepts named arguments only -- no positional calls. Often you want to allow the caller maximum flexibility and therefore the second form, as most answers assert, is preferable: but that is not always the case. When you accept many optional parameters of which typically only a few are passed, it may be an excellent idea (avoiding accidents and unreadable code at your call sites!) to force the use of named arguments --
threading.Thread is an example. The first form is how you implement that in Python 2.
The idiom is so important that in Python 3 it now has special supporting syntax: every argument after a single
* in the
def signature is keyword-only, that is, cannot be passed as a positional argument, but only as a named one. So in Python 3 you could code the above as:
def f(*, foo=None, bar=None, **kwargs): ...etc...
Indeed, in Python 3 you can even have keyword-only arguments that aren't optional (ones without a default value).
However, Python 2 still has long years of productive life ahead, so it's better to not forget the techniques and idioms that let you implement in Python 2 important design ideas that are directly supported in the language in Python 3!