Python List Comprehensions: Complete Beginner Guide

Published on: July 10, 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 = [" [email protected] ", "[email protected]"]
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

    Uso do operador in em Python para verificação em coleções
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python in Operator: Membership Tests Explained

    Learn the Python in operator with strings, lists, sets, dictionaries, ranges, generators, custom classes, not in, and efficient membership.

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026
    Leitura e escrita de arquivos CSV em Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python CSV Files: Read, Write, and Process Data

    Learn to read, write, filter, validate, and transform Python CSV files with reader, writer, DictReader, DictWriter, encoding, and streaming.

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026
    Fatiamento de listas (slicing) em Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python Slicing: Complete Guide with Examples

    Master Python slicing with start, stop, step, negative indexes, reversal, shallow copies, slice assignment, deletion, and practical examples.

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026
    Pessoa usando tablet com caneta digital para planejar tarefas em checklist, representando organização, planejamento e produtividade digital.
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python sort() vs sorted(): Complete Guide

    Understand Python sort() vs sorted(), including mutation, custom keys, reverse order, stable sorting, multiple fields, and common mistakes.

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026
    Leitura e escrita de arquivos TXT usando Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Read and Write Text Files in Python

    Learn to read, write, append, and process text files in Python with UTF-8 encoding, context managers, pathlib, and practical examples.

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026
    Uso da função enumerate em loops Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python enumerate(): Cleaner Loops with Indexes

    Learn Python enumerate() to loop with indexes, choose a custom start value, combine it with zip, process files, and avoid

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026