How to flatten a list in Python

Learn how to flatten a list in Python with various methods. Discover tips, real-world uses, and how to debug common errors.

How to flatten a list in Python
Published on: 
Fri
Feb 20, 2026
Updated on: 
Mon
Apr 6, 2026
The Replit Team

To flatten a list in Python means you convert a nested list into a single, one-dimensional list. This common data manipulation task simplifies complex data sets for analysis.

In this article, we'll explore various techniques to accomplish this. You'll find practical tips, see real-world applications, and get advice to debug common issues, so you can choose the best method.

Basic flattening with list comprehension

nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat_list = [item for sublist in nested_list for item in sublist]
print(flat_list)--OUTPUT--[1, 2, 3, 4, 5, 6, 7, 8, 9]

List comprehension is a concise and often more efficient way to flatten lists than using traditional loops with the append() method. It packs the entire logic into one readable line, making accessing list of lists straightforward.

Here’s how the nested loops work inside the expression:

  • The outer loop, for sublist in nested_list, grabs each inner list one by one.
  • The inner loop, for item in sublist, then iterates over the elements within that sublist.
  • Finally, each item is collected to form the new flat list.

Standard flattening methods

While list comprehension is a powerful one-liner, Python's standard library offers several other approaches that can be just as effective.

Using traditional for loops

nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat_list = []
for sublist in nested_list:
for item in sublist:
flat_list.append(item)
print(flat_list)--OUTPUT--[1, 2, 3, 4, 5, 6, 7, 8, 9]

This approach is more explicit than list comprehension, making it very clear what's happening. You start by initializing an empty list, flat_list, to store the results.

  • The outer loop iterates through each sublist within the nested_list.
  • The inner loop then takes over, processing each item inside that sublist.
  • Finally, the append() method adds each item to flat_list one by one.

For cases where you need both the index and value during iteration, consider using enumerate in Python.

Its straightforward nature makes it easy to read and debug.

Using the sum() function

nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat_list = sum(nested_list, [])
print(flat_list)--OUTPUT--[1, 2, 3, 4, 5, 6, 7, 8, 9]

The sum() function offers a surprisingly clever way to flatten a list. The key is providing an empty list, [], as the second argument. This acts as a starting point for the operation.

  • Python then iterates through the nested_list, using the + operator to concatenate each sublist to the running total.

This effectively merges all the sublists into one. While this approach is very concise, it can be less efficient for very large lists because a new list is created during each concatenation step.

Using itertools.chain()

import itertools

nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat_list = list(itertools.chain(*nested_list))
print(flat_list)--OUTPUT--[1, 2, 3, 4, 5, 6, 7, 8, 9]

The itertools.chain() function offers a powerful and memory-efficient way to flatten lists. It processes iterables in sequence, treating them as one continuous stream without creating new lists in memory. This makes it a great choice for performance, especially with large datasets.

  • The asterisk * before nested_list is an unpacking operator. It passes each sublist as a separate argument to chain().
  • Because chain() returns an iterator, you wrap the result in list() to build the final flattened list.

Advanced flattening techniques

While the standard methods work well for simple cases, more complex or deeply nested lists call for advanced techniques like recursion or specialized functions.

Handling deeply nested lists with recursion

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

print(flatten([1, [2, [3, 4], 5], [6, 7]]))--OUTPUT--[1, 2, 3, 4, 5, 6, 7]

Recursion is a powerful solution for lists with unknown or irregular nesting depths. The flatten() function iterates through each element, using isinstance() to check if an item is a list. This lets it handle any level of nesting.

  • If an item is a list, the function calls itself—flatten(item)—and merges the returned flat list into the main one using extend().
  • If an item is not a list, it’s simply added to the result with append().

Using functools.reduce with operator.concat

import functools
import operator

nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat_list = functools.reduce(operator.concat, nested_list)
print(flat_list)--OUTPUT--[1, 2, 3, 4, 5, 6, 7, 8, 9]

This method uses a functional programming style to flatten the list. The functools.reduce() function repeatedly applies another function to the items in your list, reducing them to a single value. Here, that function is operator.concat. For more details on using reduce in Python, check out our comprehensive guide.

  • The operator.concat function works just like the + operator, merging two lists.
  • reduce() starts by concatenating the first two sublists, then merges that result with the third, and continues until only one list remains.

It’s a concise approach, but similar to the sum() method, it can be less efficient on very large lists due to creating intermediate lists.

Memory-efficient flattening with generators

def flatten_generator(nested_list):
for item in nested_list:
if isinstance(item, list):
yield from flatten_generator(item)
else:
yield item

deep_list = [1, [2, [3, 4], 5], [6, 7]]
print(list(flatten_generator(deep_list)))--OUTPUT--[1, 2, 3, 4, 5, 6, 7]

This generator-based approach is highly memory-efficient, making it ideal for large or deeply nested lists. Instead of building a new list in memory, the flatten_generator function uses the yield keyword to produce items one by one as they are requested. Learn more about using yield in Python for advanced generator patterns.

  • When it encounters a sublist, the yield from expression delegates to a recursive call, passing up each item from the nested generator.
  • If an item isn’t a list, it’s returned directly with yield.

This creates an iterator that you can convert to a list when you need the final result.

Move faster with Replit

Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. This lets you move from learning individual techniques to building complete, working applications much faster.

Instead of piecing together methods like itertools.chain(), you can use Agent 4 to build a finished product directly from a description. For example, you could create:

  • A data utility that flattens nested API data into a simple list for a CSV export.
  • A content management tool that merges multiple lists of tags into one unified list for a database.
  • A dashboard component that aggregates metrics from various system logs into a single, flat stream for real-time monitoring.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

Even with the right tools, you might run into a few common pitfalls when flattening lists in Python.

  • Common mistake with for loop order in list comprehension: It’s easy to mix up the order of the for loops. The correct sequence—[item for sublist in nested_list for item in sublist]—mirrors traditional nested loops, with the outer loop first. Reversing them will cause a NameError because you’d be trying to access an inner item before its sublist is defined.
  • Handling non-list items when flattening mixed content: Many methods assume your list only contains other lists. If your data includes mixed types like integers or strings, methods like sum() can fail by raising a TypeError. Recursive functions that check each item's type with isinstance() are designed to navigate this issue gracefully.
  • Performance issues with sum() for large nested lists: While clever, using sum() can be a performance trap. Each time it adds a sublist, it creates a new temporary list. For a large number of sublists, this repeated creation and copying becomes very slow, which is why memory-efficient alternatives are better for larger datasets.

Common mistake with for loop order in list comprehension

It's easy to mix up the for loop order in a list comprehension. The outer loop must always come first. If you reverse the sequence, Python raises a NameError because the inner variable is referenced before it's defined. See it happen below.

nested_list = [[1, 2], [3, 4], [5, 6]]
# This will raise a NameError
flat_list = [item for item in sublist for sublist in nested_list]
print(flat_list)

The expression tries to loop through sublist before it's assigned a value from nested_list, causing the NameError. The correct implementation mirrors the structure of a traditional nested loop. See how it works in the code below.

nested_list = [[1, 2], [3, 4], [5, 6]]
flat_list = [item for sublist in nested_list for item in sublist]
print(flat_list)

The correct order works because it mirrors the logic of traditional nested loops. Always remember:

  • The outer loop, for sublist in nested_list, must come first to define the sublist variable.
  • The inner loop, for item in sublist, can then access the items within that sublist.

This sequence prevents the NameError. Keep this logical flow in mind whenever you're writing complex list comprehensions to avoid similar errors.

Handling non-list items when flattening mixed content

Flattening a list with mixed content, such as sublists alongside standalone numbers, can cause errors. Methods like list comprehension expect every item to be iterable. When they encounter a non-iterable element like an integer, they raise a TypeError.

The code below demonstrates what happens when you try to flatten a list containing both lists and integers using a standard list comprehension.

mixed_list = [[1, 2], 3, [4, 5]]
# Will raise TypeError: 'int' object is not iterable
flat_list = [item for sublist in mixed_list for item in sublist]
print(flat_list)

The inner loop, for item in sublist, fails when it encounters the integer 3. Since numbers aren't iterable, Python raises a TypeError. A recursive function that checks each item's type can navigate this issue. See the implementation below.

mixed_list = [[1, 2], 3, [4, 5]]
flat_list = []
for sublist in mixed_list:
if isinstance(sublist, list):
flat_list.extend(sublist)
else:
flat_list.append(sublist)
print(flat_list)

This solution works by checking each item's type before processing it. This is a robust way to handle lists with unpredictable or mixed data types, which you'll often find in data from APIs or user-generated content.

  • The loop uses isinstance() to see if an item is a list.
  • If it's a list, extend() unpacks its contents into the new list.
  • Otherwise, append() adds the item directly.

Performance issues with sum() for large nested lists

Using sum() to flatten lists is a neat shortcut, but it comes with a hidden cost. This method becomes surprisingly slow with large datasets because it creates a new list at each step, leading to significant performance issues. See what happens below.

# Creates a large nested list
large_nested_list = [[i] for i in range(1000)]
# Inefficient for large lists - O(n²) time complexity
flat_list = sum(large_nested_list, [])
print(len(flat_list))

The + operator builds a new list with every addition, repeatedly copying all existing elements. This inefficiency compounds quickly on large lists, making the operation much slower than necessary. See a more performant alternative in the code below.

import itertools
large_nested_list = [[i] for i in range(1000)]
# More efficient - O(n) time complexity
flat_list = list(itertools.chain.from_iterable(large_nested_list))
print(len(flat_list))

The itertools.chain.from_iterable() function offers a far more performant solution. It avoids the pitfalls of sum() by processing elements sequentially without creating temporary lists.

  • It returns a memory-efficient iterator.
  • This results in linear O(n) time complexity, making it ideal for large datasets.

You'll want to reach for this method when dealing with data from APIs or large files where speed is a priority.

Real-world applications

With an understanding of the methods and their pitfalls, you can see how list flattening solves real-world problems in data and text analysis.

Using for loops in list comprehension for text analysis

In text analysis, a nested list comprehension offers a powerful way to flatten structured text, like documents and sentences, into a simple list of words.

# Multiple documents with sentences
documents = [
["Python is powerful", "Lists are flexible"],
["Comprehensions simplify code", "Python is popular"]
]

# Extract all words for frequency analysis
all_words = [word.lower() for doc in documents
for sentence in doc
for word in sentence.split()]

from collections import Counter
word_freq = Counter(all_words)
print(dict(word_freq.most_common(3)))

This snippet shows how to find the most frequent words in a collection of documents. It's a common task in text analysis.

  • A three-level list comprehension unpacks the nested list, using split() to break sentences into individual words.
  • The lower() method ensures words like "Python" and "python" are counted as the same, which is a key step in text normalization.
  • Finally, collections.Counter tallies the words, and most_common(3) identifies the top three, giving you a quick summary of the text's content.

Extracting data from nested JSON with list comprehensions

List comprehensions provide an elegant way to flatten complex JSON data, such as API responses, into a simple list of values.

# Sample API responses with nested user activity data
api_data = [
{"users": [
{"id": 1, "activities": ["login", "search", "logout"]},
{"id": 2, "activities": ["login", "purchase"]}
]},
{"users": [
{"id": 3, "activities": ["login", "search", "purchase", "logout"]}
]}
]

# Analyze most common user activities
all_activities = [activity for response in api_data
for user in response["users"]
for activity in user["activities"]]

print(f"Total activities recorded: {len(all_activities)}")
print(f"Unique activities: {set(all_activities)}")

This code shows how a nested list comprehension can efficiently parse complex data structures, like those from an API. The expression unpacks the data layer by layer to create a flat list of all user activities, making it perfect for AI coding workflows.

  • The first loop, for response in api_data, iterates through each top-level dictionary.
  • The second loop, for user in response["users"], dives into the nested users list.
  • The final loop, for activity in user["activities"], extracts each individual activity string.

This technique is a concise and powerful way to aggregate specific data points from a nested source. After flattening the data, you might want to export it by converting JSON to CSV for further analysis.

Get started with Replit

Turn your knowledge into a real tool with Replit Agent. Describe what you want to build, like "a tool to flatten JSON API data into a CSV" or "a script to merge log files into one list."

Replit Agent will write the code, test for errors, and deploy your application directly from your browser. Start building with Replit.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.