Higher Order Functions

In Python programming, functions are more than just blocks of code to be executed. They can also be passed around as data, manipulated, and transformed. This concept lies at the heart of higher-order functions. Higher-order functions allow us to write more flexible, expressive, and concise code by treating functions as first-class citizens.

Introduction to Higher Order Functions:

In Python, functions are first-class citizens, which means they can be treated like any other object. This includes passing functions as arguments to other functions, returning functions from other functions, and storing functions in data structures.

First-Class Functions:

In Python, functions are treated as first-class citizens. This means they can be assigned to variables, passed as arguments to other functions, returned from other functions, and stored in data structures like lists or dictionaries.

Example:

				
					def greet(name):
    return f"Hello, {name}!"

greeting = greet
print(greeting("Alice"))  # Output: Hello, Alice!
				
			

Higher Order Functions (HOFs):

  • Higher order functions are functions that take other functions as arguments or return functions as results.
  • They enable a functional programming style, allowing for concise and expressive code.
  • Examples include map(), filter(), reduce(), and custom functions designed to operate on other functions.

Exploring Higher Order Functions:

The map() Function:

The map() function applies a given function to each item of an iterable (e.g., list, tuple) and returns a new iterable with the results.

Example:

				
					def square(x):
    return x ** 2

numbers = [1, 2, 3, 4, 5]
squared_numbers = map(square, numbers)
print(list(squared_numbers))  # Output: [1, 4, 9, 16, 25]
				
			

Explanation:

  • We define a function square(x) that takes a number x and returns its square.
  • We have a list of numbers [1, 2, 3, 4, 5].
  • We use the map() function to apply the square() function to each element of the numbers list.
  • The map() function returns an iterator, so we convert it to a list to see the results.
  • Finally, we print the list of squared numbers.

The filter() Function:

The filter() function filters elements from an iterable for which a given function returns True.

Example:

				
					def is_even(x):
    return x % 2 == 0

numbers = [1, 2, 3, 4, 5]
even_numbers = filter(is_even, numbers)
print(list(even_numbers))  # Output: [2, 4]
				
			

Explanation:

  • We define a function is_even(x) that takes a number x and returns True if it’s even, False otherwise.
  • We have a list of numbers [1, 2, 3, 4, 5].
  • We use the filter() function to filter out the even numbers from the numbers list.
  • The filter() function returns an iterator, so we convert it to a list to see the results.
  • Finally, we print the list of even numbers.

The reduce() Function:

  • The reduce() function applies a rolling computation to sequential pairs of values in an iterable, optionally with an initial value.
  • It’s available in the functools module.

Example:

				
					from functools import reduce

def add(x, y):
    return x + y

numbers = [1, 2, 3, 4, 5]
total = reduce(add, numbers)
print(total)  # Output: 15
				
			

Explanation:

  • We import the reduce() function from the functools module.
  • We define a function add(x, y) that takes two numbers x and y and returns their sum.
  • We have a list of numbers [1, 2, 3, 4, 5].
  • We use the reduce() function to apply the add() function cumulatively to the elements of the numbers list.
  • The reduce() function returns a single value, which is the sum of all numbers in the list.
  • Finally, we print the sum of the numbers.

Advanced Concepts

Anonymous Functions (Lambda Functions):

  • Lambda functions are small, anonymous functions defined using the lambda keyword.
  • They are often used as arguments to higher-order functions like map() and filter().

Example:

				
					numbers = [1, 2, 3, 4, 5]
squared_numbers = map(lambda x: x ** 2, numbers)
print(list(squared_numbers))  # Output: [1, 4, 9, 16, 25]
				
			

Explanation:

  • We have a list of numbers [1, 2, 3, 4, 5].
  • We use the map() function with a lambda function to square each element of the numbers list.
  • The lambda function lambda x: x ** 2 takes a single argument x and returns its square.
  • The map() function applies this lambda function to each element of the numbers list.
  • Finally, we print the list of squared numbers.

Decorators:

  • Decorators are functions that modify the behavior of other functions or methods.
  • They are higher-order functions that take a function as an argument and return a new function.

Example:

				
					def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()
				
			

In the above topic, we delved into the functools module in Python, which provides powerful tools for working with functions. We explored two key functionalities: partial() and wraps(). With partial(), we can create new functions with pre-defined default arguments, enabling code reusability and simplification. On the other hand, wraps() is invaluable when creating decorators. It preserves the metadata of the original function, ensuring that attributes such as __name__ and __doc__ are retained by the decorated function. Happy coding! ❤️

Table of Contents