Mastering Functional Programming in Python

Mastering Functional Programming in Python

Index

  1. Introduction to Functional Programming

  2. Pure Functions

  3. The map() Function

  4. The filter() Function

  5. The zip() Function

  6. The reduce() Function

  7. Lambda Expressions

  8. List Comprehensions

  9. Set and Dictionary Comprehensions

  10. Decorators

  11. Higher-Order Functions vs. First-Class Functions


1. Introduction to Functional Programming

Functional Programming (FP) is a programming paradigm that treats computation as the evaluation of mathematical functions. It emphasizes immutability, first-class functions, and pure functions, making code easier to understand and debug. Python supports functional programming features alongside its object-oriented and procedural programming capabilities.

2. Pure Functions

A pure function is a function that:

  1. Always produces the same output for the same input.

  2. Has no side effects (it does not modify external states or variables).

Example:

def add(a, b):
    return a + b  # No side effects, always returns the same output for the same input

3. The map() Function

The map() function applies a given function to all items in an iterable and returns an iterator.

Example:

def square(num):
    return num * num

numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(square, numbers))
print(squared_numbers)  # Output: [1, 4, 9, 16, 25]

4. The filter() Function

The filter() function filters elements from an iterable based on a condition provided by a function.

Example:

def is_even(num):
    return num % 2 == 0

even_numbers = list(filter(is_even, numbers))
print(even_numbers)  # Output: [2, 4]

5. The zip() Function

The zip() function combines multiple iterables element-wise into tuples.

Example:

names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
combined = list(zip(names, ages))
print(combined)  # Output: [('Alice', 25), ('Bob', 30), ('Charlie', 35)]

6. The reduce() Function

The reduce() function (from functools module) applies a function cumulatively to elements of an iterable.

Example:

from functools import reduce

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

numbers = [1, 2, 3, 4, 5]
result = reduce(multiply, numbers)
print(result)  # Output: 120

7. Lambda Expressions

A lambda expression is an anonymous function defined using the lambda keyword.

Example:

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

Using lambda with map():

numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)  # Output: [1, 4, 9, 16, 25]

8. List Comprehensions

List comprehensions provide a concise way to create lists.

Example:

squared_numbers = [x ** 2 for x in range(1, 6)]
print(squared_numbers)  # Output: [1, 4, 9, 16, 25]

9. Set and Dictionary Comprehensions

Set Comprehension:

unique_numbers = {x for x in [1, 2, 2, 3, 4, 4, 5]}
print(unique_numbers)  # Output: {1, 2, 3, 4, 5}

Dictionary Comprehension:

squared_dict = {x: x**2 for x in range(1, 6)}
print(squared_dict)  # Output: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

10. Decorators

A decorator is a function that takes another function and extends its behavior without modifying it.

Example:

def decorator_function(original_function):
    def wrapper_function():
        print("Wrapper executed before", original_function.__name__)
        return original_function()
    return wrapper_function

@decorator_function
def say_hello():
    print("Hello!")

say_hello()

Output:

Wrapper executed before say_hello
Hello!

11. Higher-Order Functions vs. First-Class Functions

  • First-Class Functions: Functions that can be assigned to variables, passed as arguments, and returned from other functions.

  • Higher-Order Functions: Functions that take other functions as arguments or return functions as results.

Example of First-Class Function:

def greet(name):
    return f"Hello, {name}!"

message = greet  # Assigning function to variable
print(message("Alice"))  # Output: Hello, Alice!

Example of Higher-Order Function:

def apply_function(func, value):
    return func(value)

double = lambda x: x * 2
print(apply_function(double, 5))  # Output: 10