Functors and their use in Python

Functors are objects that can be called like functions, providing a way to encapsulate values and apply transformations while maintaining immutability. In Python, functors are implemented using classes with the __call__ method, allowing for modular and reusable code patterns.

What is a Functor?

A functor wraps a value in a container and provides a way to apply functions to that value without modifying the original container. The key characteristic is that applying a function to a functor returns a new functor containing the transformed value.

Basic Syntax

To create a functor in Python, define a class with:

  • __init__() method to store the wrapped value
  • __call__() method to apply transformation functions
  • Optional __repr__() method for better representation

Simple Number Functor

Here's a basic functor that wraps a number and applies transformations ?

class NumberFunctor:
    def __init__(self, value):
        self.value = value
        
    def __call__(self, f):
        return f(self.value)

def square(x):
    return x * x

def double(x):
    return x * 2

# Using the functor
functor = NumberFunctor(5)
squared = functor(square)
doubled = functor(double)

print(f"Original: {functor.value}")
print(f"Squared: {squared}")
print(f"Doubled: {doubled}")
Original: 5
Squared: 25
Doubled: 10

String Functor Example

Functors work with any data type. Here's a string functor ?

class StringFunctor:
    def __init__(self, value):
        self.value = value
        
    def __call__(self, f):
        return f(self.value)

def uppercase(s):
    return s.upper()

def add_exclamation(s):
    return s + "!"

# Using string functor
functor = StringFunctor("hello world")
upper_result = functor(uppercase)
exclaim_result = functor(add_exclamation)

print(f"Original: {functor.value}")
print(f"Uppercase: {upper_result}")
print(f"With exclamation: {exclaim_result}")
Original: hello world
Uppercase: HELLO WORLD
With exclamation: hello world!

Chainable Functor

A more advanced functor that returns new functors, enabling method chaining ?

class Functor:
    def __init__(self, value):
        self.value = value
        
    def __call__(self, f):
        return Functor(f(self.value))
    
    def __repr__(self):
        return f"Functor({self.value})"

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

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

# Chaining transformations
functor = Functor(5)
result = functor(add(3))(multiply(2))(add(1))

print(f"Original: Functor(5)")
print(f"After add(3), multiply(2), add(1): {result}")
Original: Functor(5)
After add(3), multiply(2), add(1): Functor(17)

Practical Applications

Use Case Benefit Example
Data Pipeline Composable transformations ETL operations
Configuration Encapsulated settings Environment variables
Error Handling Safe transformations Maybe/Optional patterns

List Functor Example

Functors can wrap collections and apply transformations to each element ?

class ListFunctor:
    def __init__(self, items):
        self.items = items
    
    def __call__(self, f):
        return ListFunctor([f(item) for item in self.items])
    
    def __repr__(self):
        return f"ListFunctor({self.items})"

# Transform all elements
numbers = ListFunctor([1, 2, 3, 4, 5])
squared = numbers(lambda x: x ** 2)
doubled = numbers(lambda x: x * 2)

print(f"Original: {numbers}")
print(f"Squared: {squared}")
print(f"Doubled: {doubled}")
Original: ListFunctor([1, 2, 3, 4, 5])
Squared: ListFunctor([1, 4, 9, 16, 25])
Doubled: ListFunctor([2, 4, 6, 8, 10])

Conclusion

Functors provide a powerful abstraction for applying transformations while maintaining immutability and composability. They're particularly useful in functional programming patterns, data pipelines, and creating reusable transformation logic.

Updated on: 2026-03-27T13:14:27+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements