**Introduction to Python Functools**

Python is a high-level and object-oriented programming language. One of the biggest powers and advantages Python consists is to enable the functionality for writing re-usable codes using the python tools.

Python Functools is a library designed for high order functions. These functions can perform operations and can return functions also. It permits developers to design code in such a fashion that can be re-usable. Functions can be used or extended for new requirements without fully re-writing them. Python Functools module provides various such tools to attain the mentioned functionality. **Some of them are as follows **:

**Partial Function** is one of the primary tools provided by Functools. Let us understand it in detail with examples.

### Python Partial Function

Partial Functionare one of the most important tools of the Python Functools module. By using partial functions, we can replace the existing function with already passed arguments. Moreover, we can also create a new function version by adding documentation in well-mannered.

We can create a new function by passing partial arguments. We can freeze some portion of functions’ arguments which in turn results into a new object. A different way to present is that using partial, we can create a function with some defaults. Partial supports keywords and positional arguments as fixed ones.

**Let us understand it with detailed examples.**

#### How to create Partial function?

To create a partial function, partial() is used from the Functools library. Its syntax is like below:

partial(func, /, *args, ** kwargs)

This creates a partial function which in turn is calling “func” by passing fixed positional and keyword arguments. Here, we only tend to give a few required arguments for calling “func” function. Rest of the arguments are already passed in the *args and **kwargs.

#### Subscribe to our youtube channel to get new updates..!

Consider we have a below function which adds 2 numbers.

def multiply(x, y): return x * y

Now, consider the scenario where we need functions to double or triple of the given number. In such a case, we need to define new functions like below:

def multiply(x, y): return x * y def doubleNum(x): return multiply(x, 2) def tripleNum(x): return multiply(x, 3)

When only 2-3 scenarios, it is feasible to define like above. But when the requirement is to write 100 functions more like this, it doesn’t make sense to re-write the same code. Here we can use partial functions. To use partial functions, first, we need to import partial from Functools.

from functools import partial def multiply(x, y): return x * y doubleNum = partial(multiply, 2) tripleNum = partial(multiply, 3) Print(doubleNum(10)) Output: 20

As shown in the above example, default values are replaced with variables from the left. The x will be replaced by 2 and y will be replaced with 10 when doubleNum(10) is called. For this example, ordering is not making any difference, but it does in a few scenarios. Let us see that type of example to understand the ordering and replacing of variables.

from functools import partial def orderFunc(a,b,c,d): return a*4 + b*3 + c*2 + d result = partial(orderFunc,5,6,7) print(result(8)) Output: 60

### Total Ordering

Here, we have a function **orderFunc()** which is multiplying a with 4, b with 3, c with 2 and add all those values into d.

Now we have created a partial function result() which is calling orderFunc() with values 5,6 and 7. Now 5,6,7 values are replacing variables a,b,c respectively. 8 will be replacing variable d as it is being passed while calling result(). This will return **(4*5 + 6*3 + 7*2 + 8) = 60** as result.

In this scenario, the order of passed values matter as result can be different if order changes. To fix the variables, we can use keywords also instead of positional arguments. Let’s write the above code using keyword arguments.

from functools import partial def orderFunc(a,b,c,d): return a*4 + b*3 + c*2 + d result = partial(orderFunc,c=5,d=6) print(result(8,4)) Output: 60

Here, in the above example, we have fixed 5 for variabless c and 6 for variable d. 8 and 4 will replace variable a and b respectively. This equation in turn will result into (8*4+4*3+5*2+6)= 60.

Partial Functioncan be defined in loop and calculated accordingly. Let us understand this thing with the below example:

from functools import partial def add(x,y): return x + y add_partials = [] for i in range (1, 10): function = partial(add, i) add_partials.append(function) print('Sum of {} and 2 is {}'.format(i,add_partials[i-1](2))) Output: Sum of 1 and 2 is 3 Sum of 2 and 2 is 4 Sum of 3 and 2 is 5 Sum of 4 and 2 is 6 Sum of 5 and 2 is 7 Sum of 6 and 2 is 8 Sum of 7 and 2 is 9 Sum of 8 and 2 is 10 Sum of 9 and 2 is 11

Here, in this example, we are summing a range of number with 2 by re-using the function. We can call partial in the loop and utilize its functionality to calculate a sum for the range. As we can see in the output, a loop is from 1 to 10 and all numbers between them are being added to 2 using a partial function which in turn calls the function to add.

**Metadata**

Even though Partial Functionare independent functions, they hold the memory(metadata) of a function which they consist of.

from functools import partial def add(x,y): return x + y # create a new function that multiplies by 2 result = partial(add,y=5) print(result.func) print(result.keywords) Output: <function add at 0x7f27b1aab620> {'y': 5}

First call func gives function name with its memory address and second call keywords give the keywords passed to the function. Thus, Partial Functionare called self-documented from the metadata they hold of the function which powers them.

### Updating Partial Wrapper

We can update metadata for functions using another tool of the Functools module. Update_wrapper is the tool which can be used to update metadata for function. Let us see the below example to understand it more.

def multiply(x, y): """Test string.""" return x * y result = functools.partial(multiply, y=2) try: print ('Function Name:'+result.__name__) except AttributeError: print('Function Name: __no name__') print ('Function Doc:'+result.__doc__) print('Updating wrapper:') functools.update_wrapper(result, multiply) print ('Function Name:'+result.__name__) print ('Function Doc:'+result.__doc__) Output: Function Name: __no name__ Function Doc:partial(func, *args, **keywords) - new function with partial application of the given arguments and keywords. Updating wrapper: Function Name: multiply Function Doc: Test string.

Now, from the output we can see, there was no name or doc attached to function before the wrapper tool. As soon as we updated the name and doc for function using update_wrapper tool, we can see them updated in output.

**Conclusion**

Using Functools we can remove redundant code and increase the re-usability of code in Python. More we use partial functions, more we find their use cases. **Start experimenting and Have fun!**