Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to use **kwargs in Python

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.

like image 805
Kekoa Avatar asked Jul 08 '09 14:07

Kekoa


People also ask

What is the correct way to use the Kwargs statement?

The double asterisk form of **kwargs is used to pass a keyworded, variable-length argument dictionary to a function. Again, the two asterisks ( ** ) are the important element here, as the word kwargs is conventionally used, though not enforced by the language.

How do you give Kwargs in Python?

The special syntax **kwargs in function definitions in python is used to pass a keyworded, variable-length argument list. We use the name kwargs with the double star. The reason is that the double star allows us to pass through keyword arguments (and any number of them).

When should I use Kwargs?

**kwargs are good if you don't know in advance the name of the parameters. For example the dict constructor uses them to initialize the keys of the new dictionary. It is often used if you want to pass lots of arguments to another function where you don't necessarily know the options.

Why do we use * in Python?

The asterisk (star) operator is used in Python with more than one meaning attached to it. Single asterisk as used in function declaration allows variable number of arguments passed from calling environment. Inside the function it behaves as a tuple.


2 Answers

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): 
like image 176
balpha Avatar answered Sep 20 '22 20:09

balpha


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!

like image 41
Alex Martelli Avatar answered Sep 22 '22 20:09

Alex Martelli