Python Decorators and Generators: Advanced Patterns

Decorators with Arguments

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(n=3)
def greet(name):
    print(f"Hello, {name}!")

Class-based Decorators

class CountCalls:
    def __init__(self, func):
        self.func = func
        self.count = 0

    def __call__(self, *args, **kwargs):
        self.count += 1
        print(f"Call {self.count} of {self.func.__name__}")
        return self.func(*args, **kwargs)

Generator Pipelines

Generators are memory-efficient because they yield items lazily:

def read_large_file(file_path):
    with open(file_path) as f:
        for line in f:
            yield line.strip()

def filter_lines(lines, keyword):
    for line in lines:
        if keyword in line:
            yield line

pipeline = filter_lines(read_large_file("data.log"), "ERROR")
for err in pipeline:
    print(err)  # Processes one line at a time in memory

Related Articles