Photo by Shahadat Rahman on Unsplash
A Quick Guide to Higher Order Functions in Python
An Overview of First Class Functions and Lambda Functions
Python is a multi-paradigm programming language, with functional programming being one option, and functions in Python being treated as first-class objects.
In this article, we will explore the applications of treating functions as first-class objects and we will start by defining what is a first-class object.
Treating functions as First-Class Objects
We can define a first-class object as a program entity that can be:
Created at Runtime
Passed as an argument to a method or a function
Returned as a result of a function or a method
Assigned to a variable
This is the description of any object in Object Oriented Programming, and Python treats functions as objects natively.
def factorial(n):
return 1 if n < 2 else n * factorial(n - 1)
print(type(factorial))
# <class 'function'>
As we can see, Python identifies the function as an Object, which means we can do this:
def factorial(n):
return 1 if n < 2 else n * factorial(n - 1)
fact = factorial
print(fact(5))
# 123
print(list(map(factorial, range(11))))
# [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
Python’s Higher-Order Functions
A high-order function is a Function that takes another Function as an argument or returns a Function, like Python’s Built-in function sorted.
fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
print(sorted(fruits, key=len))
# ['fig', 'apple', 'cherry', 'banana', 'raspberry', 'strawberry']
Here, we pass the len
function as an argument to the sorted function.
Some of the best higher-order functions are the famous map, filter and reduce functions, but list comprehension and generator expression have replaced them since they can do the job with easier and more compact syntax.
print(list(map(factorial, range(6))))
# [1, 1, 2, 6, 24, 120]
print([factorial(n) for n in range(6)])
# [1, 1, 2, 6, 24, 120]
print(list(map(factorial, filter(lambda n: n % 2, range(6)))))
# [1, 6, 120]
print([factorial(n) for n in range(6) if n % 2])
# [1, 6, 120]
How to be anonymous? Introducing the Lambda function
The Lambda Function is an anonymous function within a Python expression created by a Lambda expression.
Lambda Functions cannot be too complicated, since they usually are one-liners and used in an argument to another function. If you feel you need to use a while loop or a try-catch block, then you’re better off with a regular function.
# Sorting a list of words by their reversed spelling using lambda
fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
print((fruits, key=lambda word: word[::-1]))
# ['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']
Generally, if you find a piece of code hard to understand because of a lambda, the best solution is to refactor following these steps:
Document the lambda function to explain what it does
If you feel like the comment does not explain enough, think of a name for the lambda function
Convert the lambda to a regular function with a def statement
Conclusion
We saw here how can Python be efficient when coding in a functional style, this has been made possible by the higher-order functions, callables and some packages provided by Python.
Further Reading
The original article is on my Blog.
The seventh and the eighth chapters of the book Fluent Python.
Third chapter of the book The Python Language Reference.
The seventh chapter of the book Python Cookbook.