Function Transformations in Python: A Quick Guide
Table of Contents
"Function transformation" is just a concise way to describe a specific type of higher-order function. It's when a function takes a function (or functions) as input and returns a new function.
All the content from our Boot.dev courses are available for free here on the blog. This one is the "Function Transformations" chapter of Learn Functional Programming in Python. If you want to try the far more immersive version of the course, do check it out!
What Is a Function Transformation?
Let's look at an example:
from collections.abc import Callable
def multiply(x: int, y: int) -> int:
return x * y
def add(x: int, y: int) -> int:
return x + y
def self_math(math_func: Callable[[int, int], int]) -> Callable[[int], int]:
def inner_func(x: int) -> int:
return math_func(x, x)
return inner_func
square_func = self_math(multiply)
double_func = self_math(add)
print(square_func(5))
# 25
print(double_func(5))
# 10
The self_math function takes a function that operates on two different parameters (e.g. multiply or add) and returns a new function that operates on one parameter twice (e.g. square or double).
How Do You Return a Function From a Function?
inner_func is defined inside self_math. It can only be referenced directly inside self_math's scope. However, it is then returned and can be captured into a new variable like square_func or double_func, and called that way.
You can build transformations that take multiple functions, too. Here's one that takes two functions as input, filter_one and filter_two, and returns a function, filter_cmd, that filters and returns the content according to the input option, using a default argument value:
from collections.abc import Callable
def get_filter_cmd(
filter_one: Callable[[str], str],
filter_two: Callable[[str], str],
) -> Callable[[str, str], str]:
def filter_cmd(content: str, option: str = "--one") -> str:
if option == "--one":
return filter_one(content)
if option == "--two":
return filter_two(content)
if option == "--three":
return filter_two(filter_one(content))
raise ValueError("invalid option")
return filter_cmd
Why Transform Functions at All?
You might be wondering:
- "When would I use function transformations in the real world?"
- "Isn't it simpler to just define functions at the top level of the code, and call them as needed?"
Good questions. To be clear, we don't just transform functions at runtime for the fun of it! We use advanced techniques like function transformation only when they make our code simpler than it would otherwise be.
Creating variations of the same function dynamically can make it a lot easier to share common functionality. Take a look at this formatter function. It accepts a "pattern" and returns a new function that formats text according to that pattern:
from collections.abc import Callable
def formatter(pattern: str) -> Callable[[str], str]:
def inner_func(text: str) -> str:
result: str = ""
i: int = 0
while i < len(pattern):
if pattern[i:i+2] == '{}':
result += text
i += 2
else:
result += pattern[i]
i += 1
return result
return inner_func
Now we can create new formatters easily:
bold_formatter: Callable[[str], str] = formatter("**{}**")
italic_formatter: Callable[[str], str] = formatter("*{}*")
bullet_point_formatter: Callable[[str], str] = formatter("* {}")
And use them like this:
print(bold_formatter("Hello"))
# **Hello**
print(italic_formatter("Hello"))
# *Hello*
print(bullet_point_formatter("Hello"))
# * Hello
What Are Closures?
90% of the time, when I use function transformations, it's because I want to create a closure. We dig into closures in the Learn Functional Programming in Python course.
For more on the building blocks, like how to define and call functions or the different kinds of functions Python supports, see Python functions. And if you're newer to the language overall, Learn to Code in Python starts from the very beginning.
Frequently Asked Questions
What is a function transformation in Python?
A function transformation is a function that takes one or more functions as input and returns a new function. It is a specific kind of higher-order function and is the foundation for techniques like closures and currying.
How do you return a function from a function in Python?
Define a new function inside an outer function and return it by name without calling it. The inner function can be captured into a variable by the caller and invoked later. Because functions are first-class values in Python, they can be returned just like any other value.
Why would you transform a function instead of just defining another one?
The main reason is code reuse. By writing the shared logic once in an outer function and returning customized inner functions, you avoid duplicating nearly identical functions. It also lets you create closures that remember values from the enclosing scope.
What is the difference between a function transformation and a closure?
A function transformation returns a new function. A closure is the inner function that remembers values from the scope where it was created. Most function transformations produce closures, so the two ideas almost always show up together.
