When you're working with real-world data in Python, you'll run into the python flatten list problem more often than you'd expect. Maybe you're pulling rows from a database query, reading chunked input from a file, or grouping results from multiple API calls — and suddenly you have a list full of smaller lists when all you wanted was one clean, flat sequence. Knowing how to flatten list python style is a practical skill that saves you time and keeps your code readable. In this guide, I'll walk you through five solid methods, explain exactly how each one works, and show you the output so nothing is left to guesswork.
Before writing any code, it's worth making sure the concept is completely clear. When you python flatten list, you're taking a structure like this:
nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
And collapsing it into a single-level list like this:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Python doesn't ship with a dedicated built-in flatten() function, unlike some other languages. Instead, it gives you several idiomatic tools to accomplish the same result — each with its own trade-offs depending on how deeply nested your data is and what you already have available in your environment.
The most beginner-friendly way to python flatten list is the classic double for loop. There's nothing hidden here — every step is visible and easy to follow, which makes it a great starting point for understanding the pattern.
The idea is straightforward: you create an empty list, loop through each inner list inside your nested list, and then loop through every individual element inside that inner list, appending each one to your result.
nested = [[10, 20, 30], [40, 50], [60, 70, 80]]
flat = []
for sublist in nested:
for item in sublist:
flat.append(item)
print(flat)
[10, 20, 30, 40, 50, 60, 70, 80]
The outer loop picks up [10, 20, 30] first, the inner loop walks through 10, 20, 30 and appends each one. Then the outer loop moves to [40, 50], and so on. The result is a perfectly ordered, single-level list. This approach to flatten list python is the most readable for anyone just starting out, and it handles any python list of lists cleanly.
List comprehensions are one of Python's most beloved features — they let you express loops in a compact, expressive single line. For the python flatten list problem, a list comprehension with two for clauses does exactly what the double loop above does, just more concisely.
The trick is that the order of the for clauses in a python flatten list comprehension mirrors the order in the nested loop version. Read it left to right and it maps directly.
nested = [["apple", "banana"], ["cherry", "date"], ["elderberry"]]
flat = [fruit for sublist in nested for fruit in sublist]
print(flat)
['apple', 'banana', 'cherry', 'date', 'elderberry']
Read that as: "give me fruit, for each sublist in nested, for each fruit in that sublist." Once that reading clicks, you'll find yourself reaching for this form constantly when you need to flatten list python style in day-to-day code.
You can also filter elements while flattening, which is something you can't do as cleanly with itertools. Just add a condition at the end of the comprehension:
nested = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat_evens = [n for sublist in nested for n in sublist if n % 2 == 0]
print(flat_evens)
[2, 4, 6, 8]
This is the most Pythonic way to python flatten list when your structure is exactly one level deep and you want the result as a regular list.
The itertools module in Python's standard library is full of tools for working with iterables, and chain() is a natural fit for the python flatten list task. It takes multiple iterables and chains them end-to-end into a single stream — which is exactly what you want when you're collapsing a python list of lists.
itertools.chain(*nested) unpacks your nested list so each inner list becomes a separate argument to chain. The * operator handles the unpacking, and chain does the joining.
import itertools
scores = [[88, 92, 79], [95, 84], [70, 77, 81, 90]]
flat_scores = list(itertools.chain(*scores))
print(flat_scores)
[88, 92, 79, 95, 84, 70, 77, 81, 90]
There's a second form worth knowing: itertools.chain.from_iterable(). Instead of unpacking with *, it accepts a single iterable and processes it lazily. For large datasets this avoids the upfront cost of spreading everything out as arguments:
import itertools
scores = [[88, 92, 79], [95, 84], [70, 77, 81, 90]]
flat_scores = list(itertools.chain.from_iterable(scores))
print(flat_scores)
[88, 92, 79, 95, 84, 70, 77, 81, 90]
Both produce the same output. flatten list python itertools style is especially clean when your source is a generator expression or you're building a pipeline of transformations, because chain.from_iterable can consume iterators lazily without materializing them into memory all at once.
All three approaches above assume your list is exactly one level deep — a list of lists. But real data can be messier. You might encounter structures like:
deep = [1, [2, [3, [4, 5]], 6], 7]
None of the previous methods can handle this because they only peel back one layer. To truly python flatten list recursively, you need a function that checks each element: if it's a list, dig into it; if it's a value, keep it.
def flatten_deep(data):
result = []
for item in data:
if isinstance(item, list):
result.extend(flatten_deep(item))
else:
result.append(item)
return result
deep = [1, [2, [3, [4, 5]], 6], 7]
print(flatten_deep(deep))
[1, 2, 3, 4, 5, 6, 7]
Here's what happens at each step: when the function hits 1, it's not a list, so it appends it. When it hits [2, [3, [4, 5]], 6], it's a list, so the function calls itself with that inner list and uses extend to merge the results back in. This continues recursively until every element has been extracted, no matter how deep the nesting goes.
A cleaner version uses a generator with yield from, which avoids building intermediate lists and delegates recursive results directly up the call chain:
def flatten_gen(data):
for item in data:
if isinstance(item, list):
yield from flatten_gen(item)
else:
yield item
deep = [[1, 2], [3, [4, [5, 6]]], 7]
print(list(flatten_gen(deep)))
[1, 2, 3, 4, 5, 6, 7]
This python nested list to flat list approach handles arbitrary nesting depth and is memory-efficient because values are produced one at a time rather than accumulated in intermediate lists.
If you're doing numerical work and already have NumPy in your environment, flattening a python flatten 2d list is a built-in operation. NumPy arrays come with a .flatten() method that returns a one-dimensional copy of the array, and a .ravel() method that returns a flattened view (without copying when the memory layout allows it).
import numpy as np
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
flat = matrix.flatten()
print(flat)
[1 2 3 4 5 6 7 8 9]
If you're starting from a regular Python list of lists — not a NumPy array — you can still use this approach by converting first:
import numpy as np
grid = [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
flat = np.array(grid).flatten().tolist()
print(flat)
[10, 20, 30, 40, 50, 60, 70, 80, 90]
The .tolist() at the end converts the NumPy array back into a standard Python list. Keep in mind that NumPy works best with uniform, rectangular structures — all sublists the same length, all values the same type. If your data is jagged or deeply nested, the recursive generator from the previous section is the better tool.
Below is a complete, runnable script that brings all five methods together. It uses different data shapes and types to show each approach doing its job in a realistic setting.
import itertools
import numpy as np
# Sample data
simple_nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
string_nested = [["red", "green"], ["blue"], ["yellow", "purple", "orange"]]
deep_nested = [1, [2, [3, [4, 5]]], [6, 7]]
matrix = [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
# Method 1 — for loop
flat_loop = []
for sublist in simple_nested:
for item in sublist:
flat_loop.append(item)
print("For loop: ", flat_loop)
# Method 2 — list comprehension
flat_comp = [item for sublist in string_nested for item in sublist]
print("List comprehension:", flat_comp)
# Method 3 — itertools.chain.from_iterable
flat_chain = list(itertools.chain.from_iterable(simple_nested))
print("itertools.chain: ", flat_chain)
# Method 4 — recursive generator
def flatten_deep(data):
for item in data:
if isinstance(item, list):
yield from flatten_deep(item)
else:
yield item
flat_recursive = list(flatten_deep(deep_nested))
print("Recursive: ", flat_recursive)
# Method 5 — NumPy
flat_numpy = np.array(matrix).flatten().tolist()
print("NumPy: ", flat_numpy)
For loop: [1, 2, 3, 4, 5, 6, 7, 8, 9]
List comprehension: ['red', 'green', 'blue', 'yellow', 'purple', 'orange']
itertools.chain: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Recursive: [1, 2, 3, 4, 5, 6, 7]
NumPy: [10, 20, 30, 40, 50, 60, 70, 80, 90]