How to use list comprehension in Python
Learn to use Python list comprehension effectively. Explore different methods, real-world applications, and how to debug common errors.

Python's list comprehension offers a powerful way to create lists from iterables. It provides a concise, readable syntax that often replaces bulkier for loops for more efficient and Pythonic code.
In this article, you'll find core techniques, practical tips, and real-world applications. You'll also get debugging advice to help you master list comprehension and write cleaner, more effective code.
Creating a list with for loop and list comprehension
numbers = [1, 2, 3, 4, 5]
squares = [num ** 2 for num in numbers]
print(squares)--OUTPUT--[1, 4, 9, 16, 25]
The traditional way to create the squares list would involve a for loop, an empty list, and an append() call inside the loop. List comprehension packs all that logic into a single, expressive line. It's not just shorter; it's often more readable once you're familiar with the syntax because it clearly states what the new list will contain.
The expression [num ** 2 for num in numbers] builds a new list by applying the operation num ** 2 to each item from the numbers iterable. This approach is more declarative, focusing on the result rather than the step-by-step process of creating it.
Intermediate list comprehension techniques
Once you're comfortable with the basic syntax, you can unlock more power by adding conditional logic and handling complex, nested data structures.
Filtering elements with the if condition
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = [num for num in numbers if num % 2 == 0]
print(even_numbers)--OUTPUT--[2, 4, 6, 8, 10]
You can add an if condition to filter items as the list is being built. The condition is placed at the very end of the expression, after the loop.
- The expression
numis only evaluated and added to the new list if the conditionnum % 2 == 0is true.
This lets you selectively include elements that meet your criteria. It's a powerful way to create subsets of data from a larger collection without writing a full for loop with an inner if statement.
Working with nested list comprehension
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)--OUTPUT--[1, 2, 3, 4, 5, 6, 7, 8, 9]
Nested list comprehensions are perfect for working with nested data structures, like a list of lists. The expression [num for row in matrix for num in row] flattens the matrix into a single list. The loops are read from left to right.
- The first part,
for row in matrix, iterates over each sublist. - The second part,
for num in row, iterates over each number within that sublist.
This structure mirrors a standard nested for loop but in a more compact form, making it a concise way to handle multi-dimensional data.
Using if-else conditional expressions
numbers = [1, 2, 3, 4, 5]
result = ["Even" if num % 2 == 0 else "Odd" for num in numbers]
print(result)--OUTPUT--['Odd', 'Even', 'Odd', 'Even', 'Odd']
You can also use an if-else expression to transform each element based on a condition. Notice the syntax is different—the conditional logic is placed at the beginning, before the for loop.
- The expression
"Even" if num % 2 == 0 else "Odd"is evaluated for every number in the list.
This structure doesn't filter items. Instead, it determines what value each new element will take, allowing you to map every item from the original iterable to a new value in the resulting list.
Advanced list comprehension applications
As you move from intermediate techniques to advanced applications, you'll see how comprehensions can handle complex logic, build new data types, and optimize performance.
Implementing multiple if conditions
numbers = range(1, 21)
result = [num for num in numbers if num % 2 == 0 if num % 3 == 0]
print(result)--OUTPUT--[6, 12, 18]
You can chain multiple if conditions to create more complex filters. Each condition is evaluated in order, and an element must pass all of them to be included in the final list. This lets you apply several criteria at once.
- This structure is equivalent to using an
andoperator in a traditional loop. In this case, the code filters for numbers that are divisible by both 2 and 3, effectively finding multiples of 6.
Converting to dictionary comprehension
names = ["Alice", "Bob", "Charlie"]
name_lengths = {name: len(name) for name in names}
print(name_lengths)--OUTPUT--{'Alice': 5, 'Bob': 3, 'Charlie': 7}
The same concise syntax you use for lists can also build dictionaries. The key difference is the use of curly braces {} and a key: value pair. This lets you create a new dictionary by iterating over any sequence.
- In this example,
name: len(name)defines each entry. The name from the list becomes the key, and its length—calculated withlen()—becomes the value.
It’s a fast and readable way to construct dictionaries from existing data, like mapping items to their properties.
Using generator expressions for memory efficiency
numbers = range(1, 11)
squares_list = [x**2 for x in numbers] # List comprehension
squares_gen = (x**2 for x in numbers) # Generator expression
print(f"List: {squares_list}\nGenerator: {type(squares_gen)}")--OUTPUT--List: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Generator: <class 'generator'>
A generator expression looks almost identical to a list comprehension but uses parentheses () instead of square brackets []. This small change has a big impact on memory. It creates a generator object that produces values on demand rather than building an entire list at once.
- The list comprehension
squares_listcomputes and stores all the squared numbers in memory immediately. - The generator expression
squares_gendoesn't hold the values. Instead, it waits to compute each value until you iterate over it, making it far more memory-efficient for large datasets.
Move faster with Replit
Replit is an AI-powered development platform where all Python dependencies pre-installed means you can skip setup and start coding instantly. Describe what you want to build, and Agent 4 handles everything—from writing the code to connecting databases and deploying it live.
Instead of piecing together techniques, you can describe the app you actually want to build and the Agent will take it from idea to working product:
- A data analysis tool that flattens a nested list of monthly sales figures into a single dataset for a dashboard.
- A user management utility that generates a dictionary of usernames and their corresponding roles from a list of employee records.
- A content filter that processes a list of user comments, categorizing them as 'approved' or 'review needed' based on specific keywords.
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 their power, list comprehensions have a few common pitfalls, from tricky syntax to subtle scope issues that can trip you up.
Fixing incorrect placement of if-else in list comprehensions
A frequent mistake is placing the if-else expression at the end of the comprehension, like you would with a simple filter. This structure is invalid and will raise a SyntaxError because Python expects the transformative expression at the beginning.
- Remember, a filtering
ifgoes at the end to decide what gets included. - An
if-elseexpression goes at the beginning to decide what each new element becomes.
Handling KeyError when using dictionary comprehension
Dictionary keys must be unique. If you build a dictionary from an iterable containing duplicate items that will become keys, the comprehension will run without error, but it will silently overwrite values. The last duplicate key encountered will be the one that sticks.
This can lead to a KeyError later if you try to access a key you assume is present but was overwritten. Always be mindful of your source data; if duplicates are possible, you may need to process the data first or decide which value to keep intentionally.
Debugging scope issues with list comprehension variables
In Python 3, the iteration variable inside a list comprehension is local to that expression. It doesn't "leak" into the global scope. For example, after running [x*2 for x in range(5)], you can't access the variable x afterward. Trying to do so will result in a NameError.
This is a good thing—it prevents the comprehension's variable from accidentally overwriting an existing variable in your code. If you need the final value of the iteration variable, a traditional for loop is the right tool for the job.
Fixing incorrect placement of if-else in list comprehensions
It's easy to mix up the syntax for filtering with the syntax for transforming. Placing an if-else at the end of a comprehension, where a simple if filter belongs, is a common tripwire that results in a SyntaxError. The following code demonstrates this incorrect placement.
numbers = [1, 2, 3, 4, 5]
# This is wrong - if-else cannot be used after the for clause
result = [num for num in numbers if num % 2 == 0 else num * 2]
print(result)
This code triggers a SyntaxError because the if-else expression is in the wrong spot. Python's grammar requires this conditional logic at the beginning, not in the filter position. Here’s how to structure it correctly.
numbers = [1, 2, 3, 4, 5]
# Correct placement: if-else goes before the for clause
result = [num if num % 2 == 0 else num * 2 for num in numbers]
print(result)
The corrected code works because the if-else expression is placed at the beginning, before the for loop. This syntax is required when you're transforming every element, not just filtering them. The expression num if num % 2 == 0 else num * 2 runs for each number, deciding what its new value will be.
- Remember: Use
if-elseat the start for transformation and a simpleifat the end for filtering.
Handling KeyError when using dictionary comprehension
A KeyError will crash your comprehension if you try accessing a key that doesn't exist in every dictionary. This often happens with inconsistent data where some dictionaries are missing expected fields. The code below shows what happens when this occurs.
user_data = [
{"name": "Alice", "age": 30},
{"name": "Bob"}, # Missing age key
{"name": "Charlie", "age": 25}
]
ages = [user["age"] for user in user_data]
print(ages)
The code fails because the comprehension attempts to access the "age" key for every user. When it reaches Bob's record, which lacks that key, a KeyError is raised. The following example shows how to handle this gracefully.
user_data = [
{"name": "Alice", "age": 30},
{"name": "Bob"}, # Missing age key
{"name": "Charlie", "age": 25}
]
ages = [user.get("age", "Unknown") for user in user_data]
print(ages)
The corrected code avoids a KeyError by using the dictionary's .get() method. Instead of crashing when a key is missing, user.get("age", "Unknown") returns a default value. This is a robust way to handle inconsistent data where some records may be missing fields, which is common when working with APIs or user inputs.
Debugging scope issues with list comprehension variables
Debugging scope issues with list comprehension variables
In Python 3, a list comprehension's iteration variable is local to that expression. It doesn't "leak" into the surrounding code. Trying to access it after the comprehension finishes will raise a NameError, as the following code demonstrates.
numbers = [1, 2, 3, 4, 5]
[num * 2 for num in numbers]
print(num) # Trying to access 'num' outside the comprehension
The code triggers a NameError on the print(num) line. Because num is scoped only to the list comprehension, it's undefined once the comprehension finishes executing. See the correct approach in the code below.
numbers = [1, 2, 3, 4, 5]
doubled = [num * 2 for num in numbers]
# Variables from comprehensions aren't available outside their scope
print(doubled) # Access the result list instead
The corrected code works because it accesses the resulting list, not the temporary iteration variable. In Python 3, the variable num is local to the comprehension and vanishes once it’s finished. This is an intentional feature to prevent it from accidentally overwriting other variables in your code. To use the result, you must assign the entire comprehension to a new variable like doubled and work with that instead.
Real-world applications
With a grasp on common pitfalls, you can now apply list comprehensions to practical tasks like file operations and data processing.
File operations with list comprehension
A common task like extracting filenames from a list of paths becomes a simple one-liner when you combine a list comprehension with a method like .split().
file_paths = ["documents/report.pdf", "images/photo.jpg", "data/data.csv"]
file_names = [path.split("/")[-1] for path in file_paths]
print(file_names)
This code transforms a list of full file paths into a new list containing only the file names. It works by iterating through each path string and applying two operations before collecting the results.
- First,
path.split("/")divides the string into parts wherever a/appears. - Then,
[-1]selects the last part from the resulting list, which is always the name of the file.
Processing structured data with list comprehension
List comprehensions are also perfect for sifting through structured data, like a list of dictionaries, to pull out just the information you need.
temperatures = [
{"city": "New York", "temp": 32},
{"city": "Los Angeles", "temp": 75},
{"city": "Chicago", "temp": 28},
{"city": "Houston", "temp": 80}
]
hot_cities = [city["city"] for city in temperatures if city["temp"] > 70]
print(hot_cities)
This comprehension efficiently sifts through a list of dictionaries, combining filtering and data extraction into one step. It’s a powerful way to reshape and refine data in a single, readable line.
- The
if city["temp"] > 70clause acts as a gatekeeper, only allowing dictionaries with a temperature above 70 to pass. - For each of those, the expression
city["city"]pulls out just the city's name, creating a new, clean list.
Get started with Replit
Turn your knowledge into a real tool. Tell Replit Agent to "build a temperature converter for Celsius to Fahrenheit" or "create a script that extracts error messages from a list of log entries."
Replit Agent writes the code, tests for errors, and deploys your app directly from your description. Start building with Replit.
Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.
Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

.png)

.png)