Background
If you are working with python you must have come across following notations:
- *args
- **kwargs
args and kwargs are just argument names. It can be replaced by any other variable name, but the important part is the syntax and how it is used. If you have come across this you would also know they are used to pass the variable number of arguments. In this post, I will try to explain how they work with some examples.
Note: If you have not installed Jupyter notebook for python, please refer to my earlier blog post: How to Install IPython Jupyter Notebook on Ubuntu
How to pass variable arguments using *args and **kwargs in Python?
Let's take cases of *args and **kwargs one at a time and then we will see some combined examples.
Understanding *args
- *args is used to take a variable number of non-keyworded arguments that are not your formal arguments.
- arguments passed in *args become iterable. Think of this as a list.
We will understand "non-keyworded" meaning better when we go to **kwargs but for now, let's try to focus on *args.
Consider the following example:
def foo(param1, *param2): print("In foo:") print(param1) print(param2)
And now if you pass:
foo(1,2,3,4)
You will get the output:
In foo:
1
(2, 3, 4)
As you can see argument 1 got mapped to param1 (your formal argument) and the rest for mapped to *param2 (*param2 is your *args. As I mentioned before variable name does not matter).
You can pass any number of params after 1 and they will be part of param2.
You can even iterate over param2 to print all variables.
def foo(param1, *param2): print("In foo:") print(param1) for no in param2: print(no)
Output:
In foo:
1
2
3
4
Understanding *kwargs
- *kwargs is used to take a variable number of keyworded arguments that are not your formal arguments. When I say keyword it means that you pass arguments by providing a name to that variable
- Think of this as a dictionary of variable name and value you passed as arguments to the function.
def bar(param1, **param2): print("In bar:") print(param1) print(param2)
And if you pass bar(1,a=2,b=3,c=4) it will output
In bar:
1
{'a': 2, 'b': 3, 'c': 4}
1 which is your formal parameter maps to param1 and rest named parameters go as dict in param2.
Obviously, you cannot pass bar(1, 2, 3, a=2,b=3,c=4)
as it does not know what to do with 2,3,4
Hopefully, now you understand what keyworded arguments are. They are basically named parameters passed in the function call.
You can also iterate it as a dictionary
def bar(param1, **param2): print("In bar:") print(param1) for key, value in param2.items(): print("{}:{}".format(key,value))
Output:
In bar:
1
a:2
b:3
c:4
Your functions would actually have both *args and **kwargs. So let's try to see a combined example
def foobar(param0, *param1, **param2): print("In foobar:") print(param0) print(param1) print(param2)
And now if you call this as foobar(1,2,3,4,a=1)
you will get the following output:
In foobar:
1
(2, 3, 4)
{'a': 1}
Again 1 is your formal parameter and maps to param0
2,3,4 are your non-keyword params that get mapped to param1
and a=1 is your keyword param that gets mapped to param2
- Note the order is important. *args should always come before **kwargs.
- Also, there cannot be positional arguments after **kwargs
- Also, you cannot do something like foobar(1,2,3,4,a=1,5) as it will not know how to map 5.
Hopefully, this clarifies differences between *args and **kwargs. You can play around more in the Jupyter notebook or python terminal if you have installed it (See the link below if you haven't)