DEV Community

Shubham Saxena
Shubham Saxena

Posted on • Edited on

How to? : *args and **kwargs in Python

Python offers several ways to pass on arguments to a function body.
Suppose we are making a function that returns the area of a rectangle. We can write the basic code like this:
image

This given function will calculate area of a given rectangle given its height and width.

Now, if we want to make this function generic to find hyper volume of a cuboid given its n dimensions, we have two ways to move forward:

  1. Change the function to take n dimensions as arguments: calculate_volume(x1, x2, x3 ... xn), this seems really messy and wont even work on n-1 dimensions.
  2. Change the function to take a list of n dimensions as a single argument:calculate_volume([x1, x2, x3, ... xn]), this seems much better, although we will have to pass on a list of dimensions which isn't really that nice.

Understanding *args:

The important part here is the *, and not the args. We can use any variable name according to the function use case.
Now let's use this to solve our current problem:

image

As the dimensions argument can take any number of arguments, we can now pass several dimensions in it to return the volume.

We can further improve this logically by using both fixed and extended arguments :
image

Now, as a valid shape will be having at least one dimension, so we can pass it as first_dimension and all other dimensions in extra_dimensions.

Understanding **kwargs

This is used for variable length keyword arguments. Use case is a function that where we dont know the arguments or we need to pass on all the arguments to some other function.
It is basically a dictionary that can hold all the keyword arguments together and we can simply iterate over its key-value pair to access them.
Example:
Here I'm making an automatic html generator which generates the tag given all its attributes. We dont need to worry about handling all the keyword arguments, we simply pass them in **tags.

image

Output: '< img src = "mountain.jpg" width = "500" height = "600" >'

Combining everything:

One real life use for these are in arguments forwarding.
Imagine we are working on a big project with several functions, and now we want to monitor the time taken for each function in the code.
Basic way would be to go to function definition and encapsulate it with in start_time and end_time, then logging out the difference as time taken. This will require heavy code change and is not advisable at all.

Another way would be to make a generic trace function that will take any other function as argument and returns the time taken by it.

image

Since the trace function is generic in nature, it doesn't care about the arguments of f. We can simply pass them as args and kwargs without changing the function definition.

For example, here we have a function that calculates the exponent value given 2 numbers (which of course has been modified for this example)
image

Although we can do this in a much elegant way, that I'll continue in the next post.

Top comments (0)