fluttersmith/py-snippetsGitHub ↗

Flatten a nested list of any depth

Lazily yield every value from arbitrarily nested iterables, treating strings as values.

Lists#nested#iterationO(n) time✓ 3 examples pass on 3.11–3.14

API responses and config files nest lists inside lists. This walks all of them and yields the values in order.

deep_flatten.py✓ ruff · mypy --strict
from collections.abc import Iterable, Iterator


def deep_flatten(items: Iterable[object]) -> Iterator[object]:
    """Yield every non-iterable value from arbitrarily nested iterables."""
    for item in items:
        if isinstance(item, Iterable) and not isinstance(item, str | bytes):
            yield from deep_flatten(item)
        else:
            yield item
  1. without this check "ab" recurses forever: "a" is iterable too
examples✓ 3 doctests · 3.11–3.14
passed on Python 3.11 to 3.14: >>> list(deep_flatten([1, [2], [[3], 4], 5]))[1, 2, 3, 4, 5]passed on Python 3.11 to 3.14: >>> list(deep_flatten(["ab", ("cd", ["ef"])]))['ab', 'cd', 'ef']passed on Python 3.11 to 3.14: >>> list(deep_flatten([[], [[]]]))[]
Edit the function or the examples and run the doctests here, on Python 3.14. Python loads only when you click (about 7 MB, cached after the first time).

How it works

  • yield from recurses into anything iterable.
  • str and bytes are iterable, and so is each character, so without the check a string recurses until it hits the recursion limit.
  • It’s a generator: wrap it in list() when you need a list.

Complexity: O(n) time, O(d) stack for depth d

Importfrom pysnippets.lists.deep_flatten import deep_flattenNo dependencies: copy deep_flatten.py into your project, or clone the repo.

Adapted from deep-flatten in 30-seconds-of-python by the 30 seconds of code contributors, CC BY 4.0. Changed: Rewritten as a generator; strings and bytes are treated as values. Suggest an edit.