A primer on *args, **kwargs, decorators for Data Scientists

Guess not since name and age order is essential.

We don’t want to write “28 is Michael years old”.

Come **kwargs in the picture.

def myprint(**kwargs): for k,v in kwargs.

items(): print(f'{k} is {v} years old')You can call this function using:myprint(Sansa=20,Tyrion=40,Arya=17)Output:———————————–Sansa is 20 years oldTyrion is 40 years oldArya is 17 years oldRemember we never defined Sansa or Arya or Tyrion as our methods arguments.

That is a pretty powerful concept.

And many programmers utilize this pretty cleverly when they write wrapper libraries.

For example, seaborn.

scatterplot function wraps the plt.

scatter function from Matplotlib.

Essentially, using *args and **kwargs we can provide all the arguments that plt.

scatter can take to seaborn.

Scatterplot as well.

This can save a lot of coding effort and also makes the code future proof.

If at any time in the futureplt.

scatter starts accepting any new arguments the seaborn.

Scatterplot function will still work.

What are Decorators?In simple terms: Decorators are functions that wrap another function thus modifying its behavior.

A simple example:Let us say we want to add custom functionality to some of our functions.

The functionality is that whenever the function gets called the “function name begins” is printed and whenever the function ends the "function name ends” and time taken by the function is printed.

Let us assume our function is:def somefunc(a,b): output = a+b return outputWe can add some print lines to all our functions to achieve this.

import timedef somefunc(a,b): print("somefunc begins") start_time = time.

time() output = a+b print("somefunc ends in ",time.

time()-start_time, "secs") return outputout = somefunc(4,5)OUTPUT:——————————————-somefunc beginssomefunc ends in 9.

5367431640625e-07 secsBut, Can we do better?This is where decorators excel.

We can use decorators to wrap any function.

from functools import wrapsdef timer(func): @wraps(func) def wrapper(a,b): print(f"{func.

__name__!r} begins") start_time = time.

time() func(a,b) print(f"{func.

__name__!r} ends in {time.

time()-start_time} secs") return wrapperThis is how we can define any decorator.

functools helps us create decorators using wraps.

In essence, we do something before any function is called and do something after a function is called in the above decorator.

We can now use this timer decorator to decorate our function somefunc@timerdef somefunc(a,b): output = a+b return outputNow calling this function, we get:a = somefunc(4,5)Output———————————————'somefunc' begins'somefunc' ends in 2.

86102294921875e-06 secsNow we can append @timer to each of our function for which we want to have the time printed.

And we are done.

Really?Connecting all the piecesWhat if our function takes three arguments?.Or many arguments?This is where whatever we have learned till now connects.

We use *args and **kwargsWe change our decorator function as:from functools import wrapsdef timer(func): @wraps(func) def wrapper(*args,**kwargs): print(f"{func.

__name__!r} begins") start_time = time.

time() func(*args,**kwargs) print(f"{func.

__name__!r} ends in {time.

time()-start_time} secs") return wrapperNow our function can take any number of arguments, and our decorator will still work.

Isn’t Python Beautiful?In my view, decorators could be pretty helpful.

I provided only one use case of decorators, but there are several ways one can use them.

You can use a decorator to debug code by checking which arguments go in a function.

Or a decorator could be used to count the number of times a particular function has been called.

This could help with counting recursive calls.

ConclusionIn this post, I talked about some of the constructs you can find in python source code and how you can understand them.

It is not necessary that you end up using them in your code now.

But I guess understanding how these things work helps mitigate some of the confusion and panic one faces whenever these constructs come up.

Understanding is vital when it comes to codingAlso if you want to learn more about Python 3, I would like to call out an excellent course on Learn Intermediate level Python from the University of Michigan.

Do check it out.

I am going to be writing more beginner friendly posts in the future too.

Let me know what you think about the series.

Follow me up at Medium or Subscribe to my blog to be informed about them.

As always, I welcome feedback and constructive criticism and can be reached on Twitter @mlwhiz.

.

. More details

Leave a Reply