Functional Features in Python

Chapter Outline

Chapter 10: Functional Features in Python

Python is a multi-paradigm language: it supports object-oriented, imperative, and functional programming styles. Functional features in Python make it easier to write concise, expressive, and reusable code.

In this chapter, we will explore:

  • First-class functions
  • Anonymous functions (lambdas) and higher-order tools: map, filter, and reduce
  • Closures and decorators
  • A project: Decorator-based Logger

10.1 First-Class Functions

In Python, functions are first-class citizens:

  • They can be assigned to variables.
  • They can be passed as arguments.
  • They can be returned from other functions.
python
def greet(name: str) -> str:
return f"Hello, {name}!"
# Assign a function to a variable
say_hello = greet
print(say_hello("Alice")) # Hello, Alice!
# Pass a function as an argument
def run_function(fn, value):
return fn(value)
print(run_function(greet, "Bob")) # Hello, Bob!

Functions behave like any other object in Python.

10.2 Lambdas and Higher-Order Functions

Lambda Functions

Lambdas are anonymous functions—small one-liners often used with higher-order functions.

python
square = lambda x: x * x
print(square(5)) # 25

map()

Applies a function to each element in an iterable.

python
numbers = [1, 2, 3, 4]
squares = list(map(lambda x: x * x, numbers))
print(squares) # [1, 4, 9, 16]

filter()

Filters elements based on a predicate (function returning True/False).

python
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4]

reduce()

Reduces an iterable to a single value by repeatedly applying a function. Note: reduce is in functools.

python
from functools import reduce
numbers = [1, 2, 3, 4]
total = reduce(lambda acc, x: acc + x, numbers, 0)
print(total) # 10

10.3 Closures

A closure is a function that remembers the variables from the scope in which it was created, even if that scope is gone.

python
def multiplier(factor):
def multiply_by(x):
return x * factor
return multiply_by
times3 = multiplier(3)
print(times3(10)) # 30

Here, multiply_by retains access to factor even after multiplier has returned.

10.4 Decorators

A decorator is a function that takes another function and returns a new function with added behavior. Common use cases: logging, timing, caching, access control.

python
1def simple_decorator(fn):
2 def wrapper(*args, **kwargs):
3 print("Before function call")
4 result = fn(*args, **kwargs)
5 print("After function call")
6 return result
7 return wrapper
8
9@simple_decorator
10def greet(name):
11 return f"Hello, {name}!"
12
13print(greet("Alice"))

Output:

bash
Before function call
After function call
Hello, Alice!

10.5 Example: Decorator-based Logger

Let’s build a logging decorator to automatically log function calls.

python
1import logging
2from functools import wraps
3
4# Configure logging
5logging.basicConfig(
6 filename="app.log",
7 level=logging.INFO,
8 format="%(asctime)s - %(levelname)s - %(message)s"
9)
10
11def log_function_call(fn):
12 """Decorator that logs function calls and their arguments."""
13 @wraps(fn) # preserves original function name/docs
14 def wrapper(*args, **kwargs):
15 logging.info("Called %s with args=%s kwargs=%s", fn.__name__, args, kwargs)
16 result = fn(*args, **kwargs)
17 logging.info("%s returned %s", fn.__name__, result)
18 return result
19 return wrapper
20
21# Example usage
22@log_function_call
23def add(a, b):
24 return a + b
25
26@log_function_call
27def greet(name):
28 return f"Hello, {name}!"
29
30if __name__ == "__main__":
31 print(add(2, 3)) # 5
32 print(greet("Alice")) # Hello, Alice!
  • The log_function_call decorator wraps any function.
  • Each time the function is called, logs are written before and after execution.
  • The @wraps decorator ensures the wrapped function keeps its metadata (__name__, docstring).

Sample Log Output (app.log)

console
2023-11-05 12:34:10,001 - INFO - Called add with args=(2, 3) kwargs={}
2023-11-05 12:34:10,002 - INFO - add returned 5
2023-11-05 12:34:10,003 - INFO - Called greet with args=('Alice',) kwargs={}
2023-11-05 12:34:10,004 - INFO - greet returned Hello, Alice!

Summary

  • First-class functions: Functions can be treated like data.
  • Lambdas: Small anonymous functions for concise expressions.
  • map, filter, reduce: Functional programming tools.
  • Closures: Inner functions that remember outer scope.
  • Decorators: Add reusable behavior to functions.
  • Project: A logging decorator that records function calls.

Next, we’ll move into Data Structures and Algorithms in Python, building efficient code with Python’s built-in collections.

Check your understanding

Test your knowledge of Advanced Object-Oriented Programming in Python

Feedback