Saturday, 10 December 2016

Python Function - Variable Length Arguments with *args and **kwargs

Python *args and **kwargs - We have been discussing Python functions and we have already covered Python function definition & call, Variable scopes and Function return values. In the last article, we started our discussion on Python function arguments and learned about how arguments can be passed in a function call, which also covers keyword arguments and optional arguments. In this article, we will study about how a function can take variable length arguments and process them. This requires knowledge of Keyword arguments and non-keyword arguments (or normal arguments), so I recommend you to go through the last article on Keyword Arguments, Defaults and Optional Arguments.


Variable Length Arguments

A Python function can use * and ** operators to accept or pass variable length argument lists. With the * operator, function can accept or pass non-keyworded variable length argument list, while with ** a function can accept keyworded variable length argument list. We can mention both of these operators in the function definition or function call. Please remember *args and **kwargs are just the naming conventions, so as to store non-keyworded argument list into args variable and keyworded argument list into kwargs variable. If you use something like *myVar and **myKWVar, that's absolutely fine.

Let's have a look on some examples to have more clarity on *args and **kwargs.

>>> def myFunction(*args):
...     print args

>>> myFunction(1, 2, 'Three', 'Four')
(1, 2, 'Three', 'Four')

In above example, we have created a simple function myFunction() that prints the value stored in args variable. When we call it with any number of non-keyworded arguments, it forms a tuple of those objects and stored it in variable args. We can check this in output. So, args being a tuple object, we can perform all tuple operations - including indexing, slicing, iterating - on it. Please check our article on Tuple - Introduction to Python Tuple

To more elaborate on this, we see another example, in which we create a function sum(), which will print the sum of the numbers provided as an argument to it. We know that, all the numbers will be stored in a tuple, available in the variable args. We then iterate over this, compute the result and print it.

>>> def sum(*args):
...     result = 0
...     for i in args:
...             result += i
...     print 'Sum = ' + str(result)

# We pass 6 arguments to 'sum()' function
>>> sum(1, 2, 3, 4, 5, 6)
Sum = 21

# Now, only 3 arguments
>>> sum(7, 8, 9)
Sum = 24

We now move on to explore **kwargs. As stated above, it stores keyworded variable list arguments, hence expects keyworded arguments, in the var_name = value format, to be provided in our function call. Lets see what will be the contents of the variable kwargs.

>>> def myFunction(**kwargs):
...     print kwargs

>>> myFunction(name='Mandar', country='India', age=25)
{'country': 'India', 'age': 25, 'name': 'Mandar'}

Well, that's a dictionary! We have already studied about dictionary and basic operations in our article - Python Dictionary Comprehension - 'dict' type. kwargs being a Python dictionary object, we can perform all dictionary operations on it.

So far, we have used *args and **kwargs in a function definition. I've already mentioned that, both of them can be used in a function call also. How? Lets see this in the following section.

Using *args and **kwargs in a Function call

To demonstrate this, we create a function which accepts 5 arguments, calculates their sum and prints the result. This is very simple.

>>> def sum(a, b, c, d, e):
...     print 'Sum = ' + str( a + b + c + d + e )

As we know, when we used *args in function definition, a tuple is created and stored in the variable args. In the similar manner, we create a tuple args containing 5 numbers and provide it in a function call as *args, so that Python unpacks them in individual arguments and assigns them to the parameters.

>>> args = (10, 20, 30, 40, 50)

>>> sum(*args)
Sum = 150

Similarly, we create a dictionary kwargs and use **kwargs in the function call, so that Python unpacks the dictionary into keyworded argument list and computes the result.

>>> kwargs = {'a':10, 'b':20, 'c':30, 'd':40, 'e':50}

>>> sum(**kwargs)
Sum = 150

Putting it together

Till now, we have learned normal arguments and variable length arguments. In variable length arguments, we have non-keyworded and keyworded arguments. Lets now see how we can use all of them in a function definition. While using all of them together, a specific order has to be followed which is -

normal_arg1, normal_arg2, ... , *args, **kwargs

>>> def myFunction(arg1, arg2, arg3, *args, **kwargs):
...     print 'First Normal Argument : ' + str(arg1)
...     print 'Second Normal Argument : ' + str(arg2)
...     print 'Third Normal Argument : ' + str(arg3)
...     print 'Non-keyworded Argument : ' + str(args)
...     print 'Keyworded Argument : ' + str(kwargs)

>>> myFunction(1, 2, 3, 4, 5, 6, 7, name='Mandar', country='India', age=25)
First Normal Argument : 1
Second Normal Argument : 2
Third Normal Argument : 3
Non-keyworded Argument : (4, 5, 6, 7)
Keyworded Argument : {'country': 'India', 'age': 25, 'name': 'Mandar'}

With this, we have come to an end of this discussion on variable length arguments. We also close our discussion on Python function arguments. Next, we will see two types of functions- Iterative functions and Recursive functions. Please put your views and opinions in the comment section below and stay tuned. Thank you!

1 comment: