What Is the Purpose and Use of **Kwargs

What is the purpose and use of **kwargs?

You can use **kwargs to let your functions take an arbitrary number of keyword arguments ("kwargs" means "keyword arguments"):

>>> def print_keyword_args(**kwargs):
... # kwargs is a dict of the keyword args passed to the function
... for key, value in kwargs.iteritems():
... print "%s = %s" % (key, value)
...
>>> print_keyword_args(first_name="John", last_name="Doe")
first_name = John
last_name = Doe

You can also use the **kwargs syntax when calling functions by constructing a dictionary of keyword arguments and passing it to your function:

>>> kwargs = {'first_name': 'Bobby', 'last_name': 'Smith'}
>>> print_keyword_args(**kwargs)
first_name = Bobby
last_name = Smith

The Python Tutorial contains a good explanation of how it works, along with some nice examples.

Python 3 update

For Python 3, instead of iteritems(), use items()

Why use **kwargs in python? What are some real world advantages over using named arguments?

Real-world examples:

Decorators - they're usually generic, so you can't specify the arguments upfront:

def decorator(old):
def new(*args, **kwargs):
# ...
return old(*args, **kwargs)
return new

Places where you want to do magic with an unknown number of keyword arguments. Django's ORM does that, e.g.:

Model.objects.filter(foo__lt = 4, bar__iexact = 'bar')

What is the benefit of using kwargs (or args) over a simple dict?

These are different things and both have their use-cases. Just a rule of thumb: If it looks like a function parameter, it should be a function parameter.

There are several neat use-cases for *args and **kwargs. One of which is passing through parameters that you don't care about at this point:

Say you have class Base and class A inherited from Base:

class Base:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z

class A(Base):
def __init__(self, n, *args, **kwargs):
super().__init__(*args, **kwargs)
self.n = n

As you see class A does not care about Base's __init__ parameters, so it just passes everything (except n that it needs) forward. So if you were to change Base's __init__ you would not need to change A.

But when you create A object you would pass parameters normally:

a = A(5, 3, y=6, z=42)

A similar idea is when you implement a decorator which you'd like to use on a function with any kind and number of arguments:

def say_hello_first(fn):
def wrapper(*args, *kwargs):
print('Hello')
return fn(*args, **kwargs)
return wrapper

@say_hello_first
def foo(x):
print(x)

@say_hello_first
def bar(a, b, c=3.14):
print((a + b) * c)

then:

>>> foo(42)
Hello
42

>>> bar(1, 2, c=3)
Hello
9

Use of **kwargs in a function as variable?

If these are mandatory argument for plot, just accept the arguments by name like all the rest; you can make them keyword-only if you like by putting them after a * (without a name, it makes the rest keyword-only; with a name, it would allow arbitrary additional positional arguments, so probably not a good idea here):

def plot(country, year1, year2, month, obs, *, zoom, mapbox_style, color_continuous_scale):

and the body of plot doesn't change.

If those arguments aren't always needed, and there's a wide variety of arguments you sometimes need in different code paths, you just need to know that **kwargs collects them as a string keyed dict (you can't dynamically allocate space for a variable number of locals, so actually making zoom conditionally defined as a raw name in local scope isn't possible), so look up the extra names the same way you would on a dict, e.g.:

fig = px.scatter_mapbox(df_to_plot, 
lat="LATITUDE",#latitude of the station
lon="LONGITUDE", #longitude of the station
hover_name="NAME", #when hovered, show the name of the station
color="coef", #color differs by coef
zoom=kwargs['zoom'], #default zoom size.
mapbox_style=kwargs['mapbox_style'], #style of the plot.
color_continuous_scale=kwargs['color_continuous_scale'], #scale of the colorbar, red to gray countinuous.

and you'll get a KeyError at lookup time if it turns out the caller failed to provide them.

What do *args and **kwargs mean?

Putting *args and/or **kwargs as the last items in your function definition’s argument list allows that function to accept an arbitrary number of arguments and/or keyword arguments.

For example, if you wanted to write a function that returned the sum of all its arguments, no matter how many you supply, you could write it like this:

def my_sum(*args):
return sum(args)

It’s probably more commonly used in object-oriented programming, when you’re overriding a function, and want to call the original function with whatever arguments the user passes in.

You don’t actually have to call them args and kwargs, that’s just a convention. It’s the * and ** that do the magic.

The official Python documentation has a more in-depth look.

Use of *args and **kwargs

The syntax is the * and **. The names *args and **kwargs are only by convention but there's no hard requirement to use them.

You would use *args when you're not sure how many arguments might be passed to your function, i.e. it allows you pass an arbitrary number of arguments to your function. For example:

>>> def print_everything(*args):
for count, thing in enumerate(args):
... print( '{0}. {1}'.format(count, thing))
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage

Similarly, **kwargs allows you to handle named arguments that you have not defined in advance:

>>> def table_things(**kwargs):
... for name, value in kwargs.items():
... print( '{0} = {1}'.format(name, value))
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit

You can use these along with named arguments too. The explicit arguments get values first and then everything else is passed to *args and **kwargs. The named arguments come first in the list. For example:

def table_things(titlestring, **kwargs)

You can also use both in the same function definition but *args must occur before **kwargs.

You can also use the * and ** syntax when calling a function. For example:

>>> def print_three_things(a, b, c):
... print( 'a = {0}, b = {1}, c = {2}'.format(a,b,c))
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat

As you can see in this case it takes the list (or tuple) of items and unpacks it. By this it matches them to the arguments in the function. Of course, you could have a * both in the function definition and in the function call.

Proper way to use **kwargs in Python

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):

Use kwargs in a function when it contains arguments not-used by the function

You can do it, just add kwargs to sub1 and it will auto-parse any named arguments you provided, and the rest will be put into kwargs:

def sub1(a, b, foo="bar", **kwargs):

That way you can still call sub1 with or without foo, but you can also call it with or without other arguments without causing an error.

main(1, 2, foo="hello")
> 1, 2, "hello"
main(1, 2, qux="hello")
> 1, 2, "bar"

How to use **kwargs to change a default value?

Use default value of dict.get

def foo(**kwargs):
key = kwargs.get("key", "default")


Related Topics



Leave a reply



Submit