Functional Programming Concepts in Python

Recursive Logic

Recursion allows functions to call themselves to break down complex problems. A common use case is calculating the total of a sequence.

def calculate_total(arr, current_idx, length, accumulator):
    if current_idx == length:
        return accumulator
    accumulator += arr[current_idx]
    return calculate_total(arr, current_idx + 1, length, accumulator)

data = [10, 20, 30, 40, 50]
print(calculate_total(data, 0, len(data), 0))
# Output: 150

First-Class and Higher-Order Functions

In Python, functions are treated as first-class citizens. They can be assigned to variables, passed as arguments, returned from other functions, and stored in data structures. A higher-order function is one that takes another function as an argument or returns a function.

def emphasize(text):
    return f'***{text.upper()}***'

def soften(text):
    return f'_{text.lower()}_'

def execute_formatter(formatter, message):
    result = formatter(message)
    print(result)

execute_formatter(emphasize, 'Hello World')
execute_formatter(soften, 'Hello World')
# Output:
# ***HELLO WORLD***
# _hello world_

Map

The map() built-in applies a specified operation to every item in an iterable, producing a new memory-efficient iterator.

def multiply_by_three(val):
    return val * 3

values = (2, 4, 6, 8)
transformed = map(multiply_by_three, values)
print(list(transformed))
# Output: [6, 12, 18, 24]

Filter

The filter() built-in constructs an iterator containing only elements that satisfy a specific condition defined by a predicate function.

def is_consonant(char):
    vowels = 'aeiou'
    return char.isalpha() and char not in vowels

chars = ['p', 'y', 't', 'h', 'o', 'n']
consonants_only = filter(is_consonant, chars)
print(list(consonants_only))
# Output: ['p', 'y', 't', 'h', 'n']

Lambda Expressions

Lambda expressions create anonymous, inline functions. They are syntactically restricted to a single expression and are often used where function objects are required temporarily.

square = lambda n: n * n
print(square(9))
# Output: 81

nums = [11, 22, 33, 44]
odds = [x for x in nums if x % 2 != 0]
print(odds)
# Output: [11, 33]

Generators

Generator Functions

Generator functions resemble regular functions but use the yield keyword instead of return to produce a sequence of values lazily, one at a time.

def count_up():
    yield 'A'
    yield 'B'
    yield 'C'

for letter in count_up():
    print(letter)

Generator Objects and Iteration

Invoking a generator function returns a generator object. This object can be iterated over using the next() function or a for loop.

def id_generator():
    yield 101
    yield 102
    yield 103

gen_obj = id_generator()
print(next(gen_obj))
print(next(gen_obj))

Generators are highly efficient for processing large data streams, such as log files, as they only yield one item at a time without loading the entire dataset into memory.

def generate_fibonacci(max_val):
    prev, curr = 0, 1
    while prev < max_val:
        yield prev
        prev, curr = curr, prev + curr

for num in generate_fibonacci(10):
    print(num)

Decorators

Decorators provide a way to modify or extend the behavior of functions or classes without permanently altering their source code. They wrap another function, executing additional logic before or after the wrapped function runs.

def trace_execution(fn):
    def wrapper():
        print('Entering function...')
        fn()
        print('Exiting function...')
    return wrapper

@trace_execution
def perform_task():
    print('Task is running.')

perform_task()
# Output:
# Entering function...
# Task is running.
# Exiting function...

The @trace_execution syntax is equivalent to assigning perform_task = trace_execution(perform_task).

Tags: python Functional Programming decorators generators lambda

Posted on Fri, 19 Jun 2026 16:51:51 +0000 by cabldawg