Functional programming is all about separation of concerns which object-oriented programming does this well right? yes. it's all about packing our code into separate chunks so that everything well-organized in each part of our code and each part is organize in a way that makes sense based on the functionality so when we say separation of concerns, we mean, each part concerned itself with one thing that is good at.
We remember in the OOPs section, how we had classes to divide up attributes and methods. Functional programming has this idea as well of separating the concerns but also separate data & functions that's how functional programmer view the world instead of combining methods and attributes we separate them up because they are two separate things there is data and this data gets interacted and acted upon but we are not going to combine both data and functions as one piece in an object that we saw in the object-oriented programming section.
In general, functional languages have an emphasis on simplicity and data & function are concerned because in the most functional programming paradigm we don't have an idea classes and objects instead functions operates on well-defined data structures like list & dictionaries that we saw, rather than belonging that data structure to an object but at the end of the day the goal of functional programming paradigm is same as the object-oriented paradigm. It is an idea of making our code,
Clean & understandable
Easy to extend
Easy to maintain
Dry & memory efficient
Functional programming typically plays a fairly small role in Python code. But it’s good to be familiar with it. Sometimes, You may even find situations where it’s advantageous to use Python’s functional programming capabilities in your own code.
1. The pure function should do not change the value of the input or any data that exists outside the function's scope.
2. The pure function should do not change the state of the program. Given the same input, a pure function will always produce the same output.
def multiply_by_2(input_numbers): new_numbers =  for n in input_numbers: new_numbers.append(n * 2) return new_numbers input_numbers = [2, 4, 6] output_numbers = multiply_by_2(input_numbers) print(input_numbers) #Output: [2, 4, 6] print(output_numbers) #Output: [4, 8, 12]
In the above example, multiply_by_2 function do not change any data outside the function's scope and the state of the program.Let's check some important functions in functional programming paradigm,
function : It is a function to which map passes each element of given iterable.
*iterables : It is a iterable which is to be mapped
input_numbers = [2, 4, 6] def multiply_by_2(item): return item * item output_numbers = list(map(multiply_by_2, input_numbers)) print(output_numbers) #Output: [4, 16, 36]
Above example 1 is a simplified version of code from the example in pure function.
names = ['Johnson', 'Michael', 'Lisa'] lower_names = list(map(str.lower, names)) print(lower_names) #Output: ['johnson', 'michael', 'lisa']
Use filter to extract values that meet certain conditions in an iterable.
function : It is a function that tests if each element of a sequence true or not.
*iterables : It is a iterable which is to be filtered.
input_numbers = [2, 4, 1, 6, 5] def only_odd(item): return item % 2 != 0 output_numbers = list(filter(only_odd, input_numbers)) print(output_numbers) #Output: [1, 5]
In the above example, filter function checks whether the element is odd or even.
input_numbers = [2, 'b', 1, 'a', 5] def num_type(item): return type(item) == int output_numbers = list(filter(num_type, input_numbers)) print(output_numbers) #Output: [2, 1, 5]
With zip you can combine multiple iterables into one data structure.
*iterables : It is a iterable which is to be zipped.
input_numbers1 = [2, 4, 1, 6, 5] input_numbers2 = [2, 4, 1, 6, 5] print(list(zip(input_numbers1, input_numbers2))) #Output: [(2, 2), (4, 4), (1, 1), (6, 6), (5, 5)]
input_numbers1 = [2, 4, 1, 6, 5] input_numbers2 = [2, 4, 1] print(list(zip(input_numbers1, input_numbers2))) #Output: [(2, 2), (4, 4), (1, 1)]
In the above example, zip takes the minimum item of list and zip it.
It's not a built-in function. It's a function from a package functools.
reduce applies a function of two arguments cumulatively to the elements of an iterable, optionally starting with an initial argument. It has the following syntax:
reduce(function, iterable[, initial])
from functools import reduce input_list = [2, 4, 1, 6, 5] def accumulator(initial, item ): return initial + item print(reduce(accumulator,input_list, 0)) #Output: 18
from functools import reduce input_list = [2, 4, 1, 6, 5] def accumulator(initial, item ): return initial + item print(reduce(accumulator,input_list, 2)) #Output: 20
A lambda function is a small anonymous function. It is a throw-away functions, i.e. they are just needed where they have been created.
A lambda functions are mainly used in combination with the functions filter(), map() and reduce().
from functools import reduce my_list = [1, 2, 3] #Square the item print(list(map(lambda item: item * 2, my_list))) # [2, 4, 6] #Filter the item by odd numbers print(list(filter(lambda item: item % 2 != 0, my_list))) # [1, 3] #Filter the item by odd numbers print(reduce(lambda acc, item : acc + item, my_list)) # 6
If you have any doubts or queries related to this chapter, get them clarified from our Python Team experts on ibmmainframer Community!