# Speed Up Function Calls In Python 3.9

A person working in Python would be familiar with  [decorators](https://www.python.org/dev/peps/pep-0318/), which is a syntactic way in python to add some functionality to a function and return it.

From python 3.9 there is a new lightweight function cache introduced in the  [functools](https://docs.python.org/3/library/functools.html)  module, which is analogous to what we know as **"Memoize"**.

This could be utilized to optimize the function calls that we make as it maintains a cache of function with its arguments and return values. This essentially avoids re-execution of the function if all the arguments are the same and returns the cached result.

**For Example**


```
from functools import cache

def monitor(func):
    def inner(*args, **kwargs):
        val = func(*args, **kwargs)
        print('Invoked', func)
        return val
    return inner

@monitor
def some_work(arg: int):
    temp = arg * 1000
    temp = temp + 1000
    return temp

@cache
@monitor
def some_smart_work(arg: int):
    temp = arg * 1000
    temp = temp + 1000
    return temp

>>> some_work(3)
Invoked <function some_work at 0x101508d30>
4000
>>> some_work(3)
Invoked <function some_work at 0x101508d30>
4000
>>> some_work(3)
Invoked <function some_work at 0x101508d30>
4000
>>> some_smart_work(3)
Invoked <function some_smart_work at 0x1015089d0>
4000
>>> some_smart_work(3) // function decorate with @cache is not invoked again, result is returned from cache.
4000
>>> some_smart_work(3)
4000
``` 

This decorator could be applied to functions that deal with I/O, Network calls, or other heavy work where chances of function getting invoked with the same arguments are high, this will avoid the need for re-execution and will speed-up the process.


