Table of Content
- Special Symbols Used for Passing Arbitrary Number of Arguments in Python
- What does the *args mean in Python and how to use it?
- What does the **kwargs mean in Python and how to use it?
- Combining *args, **kwargs, and other arguments
- Note
- TLDR Summary
- Wrap Off
The *args
and **kwargs
are common placeholders for parameters in functions to allow an arbitrary number of positional arguments and keyword arguments, respectively.
In this article, you will see in detail what are *args
and **kwargs
with examples and different ways to use them in code.
Special Symbols Used for Passing Arbitrary Number of Arguments in Python
In Python, we can pass an arbitrary number of arguments to a function using special symbols. There are two special symbols used for this:
- *args: for Positional (Non-Keyword) Arguments
- **kwargs: for Keyword Arguments
What does the *args
mean in Python and how to use it?
The *args
allows for any number of optional positional arguments (parameters), which will be assigned to a tuple named args
.
This means that *args
will give you all positional arguments sent to the function parameters as a tuple, which allows you to perform all actions that can be performed on tuples such as indexing, iterating, etc.
What does the **kwargs
mean in Python and how to use it?
The **kwargs
allows for any number of optional keyword arguments (parameters), which will be in a dict named kwargs
.
This means that **kwargs
will give you all keyword arguments sent to the function parameters, except for the parameters corresponding to a formal parameter, as a dictionary.
def bar(**kwargs):
for a in kwargs:
print(a, kwargs[a])
bar(name='one', age=27)
# name one
# age 27
Combining *args, **kwargs, and other arguments
You can mix *args, **kwargs with normal arguments to allow a set of fixed and some variable arguments in a function:
Variation 1:
def foo(*args, **kwargs):
pass
Variation 2:
def foo(kind, *args, **kwargs):
pass
Variation 3:
def foo(kind=None, *args, **kwargs):
pass
It is possible to pass arguments from a list when calling a function by unpacking the list.
def foo(bar, lee):
print(bar, lee)
l = [1,2]
foo(*l)
# 1 2
It is also possible to use this the other way around, using a dictionary:
def foo(a, b, c):
print(a, b, c)
obj = {'b':10, 'c':'lee'}
foo(100,**obj)
# 100 10 lee
Note
When you pass a Python dict
as a keyword argument passing, they are usually ordered.
However, from Python 3.6, keyword arguments are guaranteed to be ordered.
This means that the order of elements in **kwargs
now corresponds to the order in which keyword arguments were passed to the function.
From Python 3.7 upward, it's a standard to do the above.
From python 3.8 onward, you can use /
in function definition to enforce positional only parameters.
In the following example, parameters a and b are positional-only, while c or d can be positional or keyword, and e or f are required to be keywords:
def f(a, b, /, c, d, *, e, f):
pass
One reason to use /
is that it allows you to change the names of the parameters in the function and not have to update at any place where the function is called (you can be sure that no caller of the function has used the names of the parameters to supply arguments since it isn't used).
TLDR Summary
- To accept any number of positional arguments using
*args
:def foo(*args): pass
, herefoo
accepts any number of positional arguments, i.e., the following calls are validfoo(1)
,foo(1, 'bar')
- To accept any number of keyword arguments using
**kwargs
:def foo(**kwargs): pass
, here 'foo' accepts any number of keyword arguments, i.e., the following calls are validfoo(name='Tom')
,foo(name='Tom', age=33)
- To accept any number of positional and keyword arguments using
*args, **kwargs
:def foo(*args, **kwargs): pass
, herefoo
accepts any number of positional and keyword arguments, i.e., the following calls are validfoo(1,name='Tom')
,foo(1, 'bar', name='Tom', age=33)
- To enforce keyword-only arguments using
*
:def foo(pos1, pos2, *, kwarg1): pass
, here*
means that foo only accepts keyword arguments after pos2, hencefoo(1, 2, 3)
raises TypeError butfoo(1, 2, kwarg1=3)
is ok. - To express no further interest in more positional arguments using
*_
(Note: this is a convention only):def foo(bar, baz, *_): pass
means (by convention)foo
only usesbar
andbaz
arguments in its working and will ignore others. - To express no further interest in more keyword arguments using
\**_
(Note: this is a convention only):def foo(bar, baz, **_): pass
means (by convention)foo
only usesbar
andbaz
arguments in its working and will ignore others.
Wrap Off
That's what you should know about the *args
and **kwargs
and how they should be used in Python.
If you learned from this tutorial, or it helped you in any way, please consider sharing and subscribing to our newsletter.
Please share this post and for more insightful posts on business, technology, engineering, history, and marketing, subscribe to our newsletter.