Flatten a nested list in Python

Flatten one level with a comprehension or itertools.chain, and use a list-specific recursive function when the nesting depth varies.

Best practices
Python programming and application logging

For a list of lists, use a nested comprehension: [item for group in groups for item in group]. It removes one level of nesting. A recursively nested structure needs a different policy about which objects should be expanded.

Flatten one level

groups = [[1, 2], [3, 4], [5, 6]]
flat = [item for group in groups for item in group]
print(flat)  # [1, 2, 3, 4, 5, 6]

The loop order matches the equivalent statements:

flat = []
for group in groups:
    for item in group:
        flat.append(item)

Use an iterator when you do not need a list

from itertools import chain

items = chain.from_iterable(groups)
for item in items:
    print(item)

chain.from_iterable() yields values as you consume them. Calling list(chain.from_iterable(groups)) materializes the entire result, so that form does not eliminate the output list's memory cost. The input groups must themselves be iterable.

Expand nested lists recursively

def flatten(values):
    result = []
    for item in values:
        if isinstance(item, list):
            result.extend(flatten(item))
        else:
            result.append(item)
    return result

print(flatten([1, [2, [3, [4]]]]))  # [1, 2, 3, 4]

This function expands lists only. Strings, bytes, tuples, and other objects remain individual values. Deep nesting can reach Python's recursion limit, and self-referential lists need cycle detection. An iterative traversal is another option when those constraints matter.

Avoid repeated list concatenation

sum(groups, []) works for lists of lists, but repeatedly copies the accumulated prefix. Its cost can grow quadratically as the number of small groups increases. A comprehension or iterator makes the intended traversal clearer.

FAQ

What happens to strings? chain.from_iterable(["ab", "cd"]) yields individual characters. The recursive list-only function above keeps strings intact. If you generalize it to all iterables, explicitly exclude strings and bytes when they should remain atomic.

What about NumPy? array.flatten() returns a copy. array.ravel() returns a view when possible and a copy when needed; layout and order affect the result. Do not assume one is always faster for your data.

Is there a library for deeper structures? more_itertools.collapse offers configurable flattening. Check its supported container and scalar behavior rather than assuming it is identical to a list-only recursion.

References

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting