Three approaches — recursive, iterative stack, and a Python generator with yield from.
Given an arbitrarily nested list, return a flat list of all integers in order. Nesting can be any depth.
# [1, [2, [3, 4], 5], 6] → [1, 2, 3, 4, 5, 6]
# [[1, 2], [3, [4, [5]]]] → [1, 2, 3, 4, 5]
# [] → []
# [1] → [1]
If the item is a list, recurse. If it's an integer, yield it. Clean and readable.
def flatten_recursive(nested):
result = []
for item in nested:
if isinstance(item, list):
result.extend(flatten_recursive(item))
else:
result.append(item)
return result
print(flatten_recursive([1, [2, [3, 4], 5], 6])) # [1,2,3,4,5,6]
Avoid recursion by explicitly managing a stack. Safe for arbitrarily deep nesting.
def flatten_iterative(nested):
result = []
stack = [nested]
while stack:
current = stack.pop()
if isinstance(current, list):
# Push items in reverse so left-to-right order is preserved
stack.extend(reversed(current))
else:
result.append(current)
return result
print(flatten_iterative([1, [2, [3, 4], 5], 6])) # [1,2,3,4,5,6]
stack.pop() (LIFO) processes them left-to-right. Without reversed(), the output would come out backwards.yield fromThe most Pythonic approach. yield from delegates to a sub-generator, naturally handling any depth without building an intermediate list.
def flatten_gen(nested):
for item in nested:
if isinstance(item, list):
yield from flatten_gen(item)
else:
yield item
print(list(flatten_gen([1, [2, [3, 4], 5], 6]))) # [1,2,3,4,5,6]
# Works lazily — useful for huge lists:
for num in flatten_gen([1, [2, [3, [4, [5]]]]]):
print(num, end=' ') # 1 2 3 4 5
yield from iterable is equivalent to for x in iterable: yield x but is more efficient — it avoids Python's overhead of driving the inner generator loop manually. Available since Python 3.3.| Approach | Time | Space | Best for |
|---|---|---|---|
| Recursive | O(n) | O(d) call stack | Clean code, shallow nesting |
| Iterative stack | O(n) | O(n) explicit stack | Very deep nesting (avoids recursion limit) |
| Generator | O(n) | O(d) — lazy | Streaming / large data — no intermediate list |
# Bonus: one-liner using sum() (only works one level deep — don't use for arbitrary nesting)
# sum([[1,2],[3,4],[5]], []) → [1, 2, 3, 4, 5]
#
# For arbitrary depth, itertools.chain.from_iterable only flattens one level too.
# The generator approach is always the right answer for arbitrary depth.
yield from. Then note the recursive approach is O(d) space due to the call stack, so the iterative version is safer for adversarial inputs.