Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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.
