Python List Comprehensions: Transform and Filter

Updated on: August 20, 2026
Reading time: 5 minutes
Introdução ao Python para iniciantes

List comprehensions are one of Python’s most recognizable features. They create a new list from an iterable while expressing transformation and optional filtering in a compact form. Used well, they remove repetitive setup and make simple data pipelines easy to read. Used poorly, they compress too much logic into one difficult line.

This guide explains Python list comprehensions from the basic syntax through conditions, nested loops, dictionaries, sets, generator expressions, and practical style decisions. It assumes you know the fundamentals of Python loops and lists.

The basic pattern

A list comprehension has the form [expression for item in iterable]. Python evaluates the expression for every item and collects the results in a new list.

numbers = [1, 2, 3, 4, 5]
squares = [number ** 2 for number in numbers]

print(squares)

The equivalent regular loop is longer but follows the same steps.

numbers = [1, 2, 3, 4, 5]
squares = []

for number in numbers:
    squares.append(number ** 2)

print(squares)

The official Python tutorial on list comprehensions presents them as a concise way to create lists where each element is the result of an operation.

Transform strings

names = [" ada ", "GRACE", " guido"]
cleaned = [name.strip().title() for name in names]

print(cleaned)

The expression can call methods and functions. Keep it focused on one understandable transformation. If it needs error handling, several temporary variables, or side effects, a normal loop is usually clearer.

Filter with an if clause

Place an if after the loop clause to include only matching items.

numbers = range(1, 21)
even_squares = [number ** 2 for number in numbers if number % 2 == 0]

print(even_squares)

Read it from left to right: create number ** 2 for each number in the range if the number is even. The condition filters before the expression is collected.

Conditional expressions inside a comprehension

An inline if/else chooses between two output values and appears before the for. It transforms every input rather than removing items.

scores = [95, 72, 88, 61]
labels = ["pass" if score >= 70 else "fail" for score in scores]

print(labels)

Compare the two roles: [x for x in values if condition] filters; [a if condition else b for x in values] maps every value. The guide to the Python conditional expression explains the inline form.

Use functions for complex transformations

A helper function keeps validation and branching testable while the comprehension describes collection.

def normalize_email(value: str) -> str:
    email = value.strip().lower()

    if "@" not in email:
        raise ValueError(f"Invalid email: {value!r}")

    return email

raw = [" ADA@example.com ", "grace@example.com"]
emails = [normalize_email(value) for value in raw]

print(emails)

This is preferable to packing several checks into the comprehension. It also works well with type hints and unit tests.

Nested comprehensions

A comprehension can contain multiple for clauses. Their order matches nested loops.

pairs = [
    (letter, number)
    for letter in ["A", "B"]
    for number in [1, 2, 3]
]

print(pairs)

Equivalent loops make the order explicit.

pairs = []

for letter in ["A", "B"]:
    for number in [1, 2, 3]:
        pairs.append((letter, number))

One or two short clauses may be readable. Deeply nested comprehensions usually deserve named loops or helper functions.

Flatten a list of lists

matrix = [
    [1, 2, 3],
    [4, 5, 6],
]

flat = [value for row in matrix for value in row]
print(flat)

This follows the same outer-then-inner loop order. For arbitrary nested structures, a recursive function or specialized iterator is more appropriate than adding more clauses.

Build a matrix

rows = 3
columns = 4

matrix = [
    [0 for _ in range(columns)]
    for _ in range(rows)
]

print(matrix)

Each inner comprehension creates a distinct list. By contrast, [[0] * columns] * rows repeats references to the same inner list, so changing one row can change all rows.

Dictionary and set comprehensions

The same concept creates dictionaries and sets. A dictionary comprehension uses a key-value pair; a set comprehension automatically removes duplicates.

words = ["python", "api", "database"]

lengths = {word: len(word) for word in words}
initials = {word[0].upper() for word in words}

print(lengths)
print(initials)

Learn more about these result types in the guides to dictionaries and sets.

List comprehension versus map and filter

Comprehensions are often easier to read when the transformation is a small Python expression. map() is attractive when an existing named function already describes the operation, and filter() may fit a reusable predicate.

values = ["1", "2", "3"]

with_comprehension = [int(value) for value in values]
with_map = list(map(int, values))

print(with_comprehension == with_map)

The comparison in map and filter in Python discusses both styles. Prefer whichever communicates intent to your team.

List comprehension versus generator expression

Square brackets create the entire list immediately. Parentheses create a generator expression that yields values lazily.

squares_list = [number ** 2 for number in range(1_000)]
squares_generator = (number ** 2 for number in range(1_000))

print(type(squares_list).__name__)
print(type(squares_generator).__name__)

Use a list when you need indexing, repeated iteration, length, or all values at once. Use a generator when values can be consumed once and the input may be large. The article on list comprehensions versus generator expressions explores memory and behavior in detail.

The walrus operator in a comprehension

An assignment expression can reuse a computed value, but it should improve rather than obscure readability.

strings = ["12", "bad", "30", "-4"]

positive = [
    number
    for text in strings
    if text.lstrip("-").isdigit()
    and (number := int(text)) > 0
]

print(positive)

This avoids converting the same valid string twice, but a helper function may still be clearer in production. See the walrus operator guide before adopting the pattern broadly.

Avoid side effects

A comprehension should create a collection. Do not use it only to call print(), append elsewhere, write files, or update global state. A normal loop clearly communicates that actions—not a new list—are the purpose.

names = ["Maya", "Noah", "Liam"]

for name in names:
    print(name)

A practical data-cleaning example

records = [
    {"name": " Ada ", "active": True, "score": "91"},
    {"name": "Grace", "active": False, "score": "88"},
    {"name": " Guido ", "active": True, "score": "95"},
]

active_users = [
    {
        "name": record["name"].strip(),
        "score": int(record["score"]),
    }
    for record in records
    if record["active"]
]

print(active_users)

The comprehension is acceptable because the transformation and filter are still short. For CSV imports, missing keys, bad numbers, or optional values require a regular loop with explicit error handling. See working with CSV files for a complete pipeline.

Common mistakes

  • Writing a comprehension so long that readers must mentally execute it.
  • Confusing the filtering if with an inline if/else expression.
  • Using a comprehension only for side effects.
  • Creating a huge list when a generator would be enough.
  • Adding multiple nested loops and conditions without helper functions.
  • Assuming a comprehension modifies the source list—it creates a new collection.

Frequently asked questions

Are comprehensions faster than loops?

They are often efficient because the iteration is implemented compactly, but performance depends on the work performed. Readability and correct memory behavior matter more than small timing differences in most application code.

Can I use try/except inside a comprehension?

Not as a statement. Put exception handling in a helper function or use a normal loop where rejected inputs can be reported clearly.

Can a comprehension create a tuple?

Parentheses around a comprehension create a generator expression, not a tuple. Wrap it with tuple(...) when an immutable tuple result is required.

Final thoughts

Python list comprehensions are ideal for one clear transformation with an optional simple filter. Extract complex logic into functions, switch to ordinary loops when actions or error reporting dominate, and choose a generator expression when materializing every result would waste memory. Concision is valuable only when the result remains immediately understandable.

Share:

Facebook
WhatsApp
Twitter
LinkedIn

Article content

    Related articles

    Programador pensando enquanto analisa código em dois monitores
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Learn Programming from Scratch: Logic and Projects

    Learn programming from scratch with a practical roadmap covering logic, languages, tools, exercises, projects, debugging, Git, and consistent study habits.

    Ler mais

    Tempo de leitura: 6 minutos
    10/07/2026
    ícone de loop com o texto 'For' abaixo
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python for Loops: Iterate over Lists and Data

    Learn Python for loops with sequences, range, enumerate, zip, dictionaries, nested loops, break, continue, comprehensions, and practical examples.

    Ler mais

    Tempo de leitura: 4 minutos
    10/07/2026
    Manipulação e formatação de strings em Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python Strings: Methods, Slicing, and Formatting

    Learn Python strings with creation, indexing, slicing, methods, formatting, Unicode, searching, validation, splitting, joining, and practical examples.

    Ler mais

    Tempo de leitura: 4 minutos
    10/07/2026
    código Python de uma tupla com o texto separado formando a frase "O que são tuplas?"
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python Tuples: Immutability and Unpacking

    Learn Python tuples with creation, packing, unpacking, indexing, immutability, methods, named records, function returns, and practical examples.

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026
    símbolo de PI
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python Floats: Precision and Rounding

    Learn Python floats with decimal values, arithmetic, conversion, rounding, precision limits, comparisons, Decimal, math functions, and practical examples.

    Ler mais

    Tempo de leitura: 4 minutos
    10/07/2026
    notebook mostrando tela a teclado
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python I/O: input(), print(), and Files

    Learn Python input and output with input(), print(), conversions, validation, formatting, files, command-line arguments, and practical interactive programs.

    Ler mais

    Tempo de leitura: 4 minutos
    10/07/2026