Functions as Objects
Functions as Objects and First-Class Functions in Python
In Python, functions are first-class objects, which means they can be:
- Assigned to variables
- Passed as arguments to other functions
- Returned from other functions
- Stored in data structures
- Have attributes and methods
1. Functions as Objects
In Python, everything is an object, including functions. When you define a function, you’re creating a function object.
python
def greet(name):
return f"Hello, {name}!"
# The function is an object with type 'function'
print(type(greet)) # <class 'function'>
print(greet) # <function greet at 0x...>
# Functions have attributes
print(greet.__name__) # 'greet'
print(greet.__doc__) # None (unless you add a docstring)
2. Assigning Functions to Variables
python
def square(x):
return x * x
# Assign function to variable
my_func = square
# Use the variable as a function
result = my_func(5)
print(result) # 25
# The variable references the same function
print(my_func is square) # True
3. Passing Functions as Arguments
python
def apply_operation(func, value):
"""Apply a function to a value"""
return func(value)
def double(x):
return x * 2
def triple(x):
return x * 3
# Pass different functions as arguments
print(apply_operation(double, 5)) # 10
print(apply_operation(triple, 5)) # 15
print(apply_operation(square, 5)) # 25
4. Returning Functions from Functions
python
def create_multiplier(factor):
"""Return a function that multiplies by the given factor"""
def multiplier(x):
return x * factor
return multiplier
# Create specialized functions
double = create_multiplier(2)
triple = create_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
5. Storing Functions in Data Structures
python
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
return a / b
# Store functions in a list
operations = [add, subtract, multiply, divide]
# Use functions from the list
a, b = 10, 5
for operation in operations:
result = operation(a, b)
print(f"{operation.__name__}({a}, {b}) = {result}")
6. Practical Example: Custom Sorting
python
# List of people with name and age
people = [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 30},
{"name": "Charlie", "age": 20}
]
# Sort by age using a lambda function
people_sorted_by_age = sorted(people, key=lambda person: person["age"])
print("Sorted by age:", people_sorted_by_age)
# Sort by name length
people_sorted_by_name_length = sorted(people, key=lambda person: len(person["name"]))
print("Sorted by name length:", people_sorted_by_name_length)
7. Function Attributes and Methods
python
def example_function(x):
"""This is a docstring"""
return x ** 2
# Add custom attributes
example_function.author = "John Doe"
example_function.created_at = "2023-01-01"
# Access attributes
print(example_function.__name__) # 'example_function'
print(example_function.__doc__) # 'This is a docstring'
print(example_function.author) # 'John Doe'
print(example_function.created_at) # '2023-01-01'
8. Higher-Order Functions
Python has built-in higher-order functions that accept other functions as arguments:
python
numbers = [1, 2, 3, 4, 5] # map() applies a function to each element squared = list(map(lambda x: x**2, numbers)) print(squared) # [1, 4, 9, 16, 25] # filter() keeps elements where function returns True even = list(filter(lambda x: x % 2 == 0, numbers)) print(even) # [2, 4] # sorted() with custom key words = ["apple", "banana", "cherry", "date"] sorted_by_length = sorted(words, key=len) print(sorted_by_length) # ['date', 'apple', 'banana', 'cherry']
Key Points:
- First-class functions mean functions can be treated like any other object
- This enables functional programming patterns in Python
- Functions can be passed around and used flexibly
- Enables powerful patterns like decorators, closures, and callback functions
- Makes code more modular and reusable
This flexibility is what makes Python such a powerful language for both object-oriented and functional programming paradigms.