Functional Programming in Python

Welcome to our exploration of functional programming in Python! In this lesson, we’ll dive into how Python supports functional programming paradigms and compare these features with their JavaScript counterparts. As a JavaScript developer, you’ll find many familiar concepts, but with a Pythonic twist.

First-Class Functions and Higher-Order Functions

Both Python and JavaScript treat functions as first-class citizens, meaning functions can be assigned to variables, passed as arguments, and returned from other functions.

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

welcome = greet
print(welcome("Alice"))  # Output: Hello, Alice!
// JavaScript
const greet = (name) => `Hello, ${name}!`;
const welcome = greet;
console.log(welcome('Alice')); // Output: Hello, Alice!

Higher-order functions, which can accept or return other functions, are also supported in both languages:

# Python
def apply_twice(func, arg):
    return func(func(arg))

def add_five(x):
    return x + 5

print(apply_twice(add_five, 10))  # Output: 20
// JavaScript
const applyTwice = (func, arg) => func(func(arg));
const addFive = (x) => x + 5;
console.log(applyTwice(addFive, 10)); // Output: 20

Lambda Functions

Python’s lambda functions are similar to JavaScript’s arrow functions, but with some key differences:

# Python
square = lambda x: x ** 2
print(square(4))  # Output: 16
// JavaScript
const square = (x) => x ** 2;
console.log(square(4)); // Output: 16

In Python, lambda functions are limited to a single expression, while JavaScript’s arrow functions can have more complex bodies.

Map, Filter, and Reduce

Python provides built-in map() and filter() functions, similar to JavaScript’s array methods:

# Python
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
evens = list(filter(lambda x: x % 2 == 0, numbers))

print(squared)  # Output: [1, 4, 9, 16, 25]
print(evens)    # Output: [2, 4]
// JavaScript
const numbers = [1, 2, 3, 4, 5];
const squared = numbers.map((x) => x ** 2);
const evens = numbers.filter((x) => x % 2 === 0);

console.log(squared); // Output: [1, 4, 9, 16, 25]
console.log(evens); // Output: [2, 4]

Python’s reduce() function is available from the functools module:

# Python
from functools import reduce

sum = reduce(lambda x, y: x + y, numbers)
print(sum)  # Output: 15
// JavaScript
const sum = numbers.reduce((x, y) => x + y);
console.log(sum); // Output: 15

Immutability and Pure Functions

While Python doesn’t enforce immutability by default, you can adopt functional programming practices to write more predictable and easier-to-test code:

# Python
def add_to_list(lst, item):
    return lst + [item]  # Creates a new list instead of modifying the original

original = [1, 2, 3]
new_list = add_to_list(original, 4)
print(original)  # Output: [1, 2, 3]
print(new_list)  # Output: [1, 2, 3, 4]

This approach is similar to how you might handle immutability in JavaScript:

// JavaScript
const addToList = (list, item) => [...list, item];

const original = [1, 2, 3];
const newList = addToList(original, 4);
console.log(original); // Output: [1, 2, 3]
console.log(newList); // Output: [1, 2, 3, 4]

Conclusion

In this lesson, we’ve explored how Python supports functional programming paradigms, drawing parallels with JavaScript. We’ve seen that while the syntax may differ, many concepts are shared between the two languages. Python’s functional features, combined with its readability and extensive standard library, make it a powerful tool for functional programming.

In our next lesson, we’ll dive into asynchronous programming with Python, exploring how Python’s async/await syntax compares to JavaScript’s approach to handling asynchronous operations. We’ll look at Python’s asyncio library and how it relates to JavaScript’s Promise-based asynchronous programming model.