Python itertools Module

The itertools module provides a collection of fast, memory-efficient tools for working with iterators. These functions create iterators for efficient looping, combining, and filtering of data sequences without materializing entire lists in memory.

Use Cases:
- Generating permutations and combinations for combinatorial problems
- Chaining multiple iterables into a single sequence
- Creating infinite iterators for counting, cycling, or repeating
- Grouping consecutive elements with groupby
- Filtering elements with takewhile and dropwhile

Example 1: Generating all pairs from two lists
    from itertools import product
    colors = ["red", "blue"]
    sizes = ["S", "M", "L"]
    combos = list(product(colors, sizes))
    print(combos)
    # [('red', 'S'), ('red', 'M'), ('red', 'L'),
    #  ('blue', 'S'), ('blue', 'M'), ('blue', 'L')]

Example 2: Batching items into fixed-size groups
    from itertools import islice
    def batched(iterable, n):
        it = iter(iterable)
        while True:
            batch = list(islice(it, n))
            if not batch:
                break
            yield batch
    data = range(10)
    for batch in batched(data, 3):
        print(batch)
    # [0, 1, 2], [3, 4, 5], [6, 7, 8], [9]

The module also includes accumulate for running totals, starmap for applying functions to pre-zipped arguments, and chain.from_iterable for flattening nested iterables. In Python 3.12+, itertools.batched is available as a built-in.
