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
Cross-Platform Space Remaining on Volume Using Python
Force Python to Use an Older Version of Module (Than What I Have Installed Now)
How to Update a Python Package
How to Listen For 'Usb Device Inserted' Events in Linux, in Python
How to Convert String Representation of List to a List
How to Detect Collision in Pygame
"Is" Operator Behaves Unexpectedly With Integers
How to Make a Python, Command-Line Program Autocomplete Arbitrary Things Not Interpreter
How to Update-Alternatives to Python 3 Without Breaking Apt
Understanding Python Subprocess.Check_Output'S First Argument and Shell=True
How to Pass a Variable by Reference
Change Default Python Version from 2.4 to 2.6
How to Download a File Over Http
Selenium Using Python - Geckodriver Executable Needs to Be in Path
MySQL_Config Not Found When Installing MySQLdb Python Interface