Python • Collections and Strings

List Comprehensions — Use list comprehensions for mapping/filtering (intro-to-standard)

Build powerful new lists in a single readable line by transforming and filtering data with Python's elegant comprehension syntax.

Code braces with terminal and markup symbols representing Python programming.
Inside this lesson 10 sections 5 questions 8 figures

SECTION 1

Historical Context & Motivation

Before list comprehensions existed in Python, programmers had to write multi-line loops every time they wanted to create a new list from an existing one. Whether you needed to double every number, extract only the even values, or convert a batch of temperatures from Celsius to Fahrenheit, the pattern was always the same: initialize an empty list, write a for loop, and call .append() inside it. This repetitive boilerplate made code longer than it needed to be and harder to read at a glance.

The idea of expressing list creation declaratively—saying what you want rather than how to build it—comes from mathematics and functional programming. Languages like Haskell had a feature inspired by set-builder notation in math, where you define a set by describing the properties its members must satisfy. Python adopted this concept and gave it a clean, readable syntax.

1990 • Haskell's List Comprehensions

The Haskell programming language popularized list comprehensions, borrowing the concept from set-builder notation in mathematics. This showed that lists could be defined declaratively.

2000 • Python 2.0 Introduces List Comprehensions

PEP 202 brought list comprehensions into Python, allowing developers to replace common for-loop-and-append patterns with a single, expressive line of code.

2006 • Conditional Filtering Added

Python's comprehension syntax matured to include optional if-clauses for filtering, enabling both mapping and filtering in one concise expression.

2008 • Python 3.0 and Beyond

Python 3 carried list comprehensions forward and added dictionary and set comprehensions, cementing the pattern as a core Python idiom used daily by millions of developers.

The central question that list comprehensions answer is straightforward: How can we transform or filter a collection into a new list without writing repetitive loop boilerplate? Understanding this tool will make your Python code shorter, cleaner, and more Pythonic.

SECTION 2

Core Principles & Definitions

A list comprehension is a compact way to create a new list by applying an expression to each item in an existing iterable, optionally filtering items with a condition. To master them, you need to understand four foundational ideas.

1

Mapping (Transformation)

Mapping means applying a function or expression to every element. For example, squaring each number in a list is a mapping operation. The expression at the start of a comprehension defines the transformation.
2

Filtering (Selection)

Filtering means keeping only items that satisfy a condition. The optional if clause at the end of a comprehension acts as a gatekeeper, letting through only the elements you want.
3

Iterable Source

The iterable is the data source you loop over—a list, range, string, or any object you can iterate through. The for x in iterable clause specifies what you're iterating over and names each element.
4

Output Expression

The output expression sits at the very beginning of the comprehension—before the for keyword. It defines what each element in the new list will look like. It can be the item itself, a calculation, a function call, or even a method call like x.upper().
✦

KEY TAKEAWAY

Think of a list comprehension like a factory assembly line. Raw materials (the iterable) enter the line. A quality inspector (the if clause) rejects items that don't pass inspection. A machine (the output expression) transforms each approved item into a finished product. All the finished products roll off the line into a shiny new list.

SECTION 3

Visual Explanation — Anatomy of a List Comprehension

Anatomy of a List Comprehension[x ** 2forxinrange(10)ifx % 2 == 0]Output ExpressionLoop VariableIterable SourceFilter ConditionExecution Flow1. Iterate source2. Apply filter3. Transform item4. Add to list
The diagram above labels each part of the comprehension [x ** 2 for x in range(10) if x % 2 == 0]. The output expression comes first, then the iterable source, and finally the optional filter condition. The bottom row shows the execution flow from left to right.

Notice the order of reading differs from the order of execution. You read the expression first (x ** 2), but Python executes the for clause first to pull each item, then checks the if condition, and only then evaluates the output expression for items that pass. This "conclusion first" style is what makes comprehensions so readable once you get used to them—you immediately see what the resulting list will contain.

SECTION 4

How It Works — Syntax Patterns

List comprehensions follow two main patterns. The first is pure mapping, where every element from the source is transformed and included. The second combines mapping with filtering, where only elements meeting a condition are transformed and included.

MAPPING PATTERN

[expressionforvariableiniterable][expression for variable in iterable]

expression — any valid Python expression that uses variable; variable — the name given to each item; iterable — the source collection (list, range, string, etc.)

MAPPING + FILTERING PATTERN

[expressionforvariableiniterableifcondition][expression for variable in iterable if condition]

condition — a boolean expression. Only items where condition evaluates to True will have the expression applied and appear in the output list.

Equivalence to a For Loop

Every list comprehension can be rewritten as a traditional for loop. The comprehension [x * 3 for x in nums if x > 0] is exactly equivalent to initializing an empty list, writing for x in nums:, checking if x > 0:, and appending x * 3. The comprehension just compresses those four lines into one. Understanding this equivalence is crucial—if you can write the loop version, you can write the comprehension, and vice versa.

LOOP EQUIVALENT

result=[]forxinnums:ifx>0:result.append(x∗3)result = [] for x in nums: if x > 0: result.append(x * 3)

This four-line pattern produces the same output as result = [x * 3 for x in nums if x > 0].

SECTION 5

Common Patterns & Detailed Breakdown

List comprehensions appear in many recurring patterns in real Python code. Below is a visual catalog of the most common ones, followed by a detailed table showing how each pattern translates from a loop into a comprehension.

Common List Comprehension Patterns① Pure Mappingnums = [1, 2, 3, 4][n * 10 for n in nums]→ [10, 20, 30, 40]② Pure Filteringnums = [1, 2, 3, 4, 5, 6][n for n in nums if n % 2 == 0]③ Map + Filterwords = ["hi", "hello", "hey"][w.upper() for w in words if len(w) > 2④ Type Conversionstrs = ["3", "14", "7"][int(s) for s in strs]→ [3, 14, 7]⑤ String Processingname = "Python"[ch.lower() for ch in name if ch != 'o'⑥ Using range()[i ** 2 for i in range(1, 6)]→ [1, 4, 9, 16, 25]General Template:[ expression for variable in iterable if condition ]
Six common patterns are shown. Patterns ①, ④, and ⑥ are pure mapping (no if). Pattern ② is pure filtering (the expression is just the variable itself). Patterns ③ and ⑤ combine mapping and filtering together.
PatternComprehensionResult
Double every number[x * 2 for x in [1, 2, 3]][2, 4, 6]
Keep positives only[x for x in [-1, 3, -5, 7] if x > 0][3, 7]
Lengths of long words[len(w) for w in words if len(w) > 3]Lengths of words with 4+ chars
Uppercase initials[name[0].upper() for name in names]First letter of each name, uppercased

Common comprehension patterns with example input and output

SECTION 6

Worked Example — Processing Student Scores

Let's walk through a realistic scenario. You have a list of student test scores, and you need to build a new list containing only the passing scores (70 or above), converted to letter-grade descriptors. We'll solve this step by step, first identifying the mapping and filtering components, then combining them into a comprehension.

Extracting and Labeling Passing Scores

  1. 1

    Step 1 — Identify the Data

    We start with a list of integer scores: scores = [85, 42, 91, 68, 77, 55, 99]. This is our iterable source.
  2. 2

    Step 2 — Define the Filter Condition

    We only want passing scores. A passing score is 70 or above, so our filter condition is s >= 70. This will exclude 42, 68, and 55.
    Filter: if s >= 70
  3. 3

    Step 3 — Define the Output Expression

    We want to label each passing score. We'll use an f-string to create descriptive text. The output expression is f"{s} — Pass". This is the mapping transformation.
    Expression: f"{s} — Pass"
  4. 4

    Step 4 — Assemble the Comprehension

    We combine all three parts into the comprehension template: expression, for-clause, if-clause.
    result = [f"{s} — Pass" for s in scores if s >= 70]
  5. 5

    Step 5 — Verify the Output

    Python iterates through each score: 85 passes → "85 — Pass", 42 fails the condition and is skipped, 91 passes → "91 — Pass", 68 is skipped, 77 passes → "77 — Pass", 55 is skipped, 99 passes → "99 — Pass".
    ["85 — Pass", "91 — Pass", "77 — Pass", "99 — Pass"]
💡

Pro Tip

When writing a comprehension, start by writing the equivalent for-loop first. Once it works, rearrange it into the comprehension format. The expression moves to the front, the for clause stays in the middle, and the if clause goes at the end.

SECTION 7

Comprehensions vs. For Loops — Strengths & Limitations

List comprehensions are a powerful tool, but they aren't always the best choice. Understanding when to use them—and when to stick with a traditional for loop—is a mark of a thoughtful programmer.

CriteriaList ComprehensionTraditional For Loop
ReadabilityExcellent for simple transformations; one line tells the whole storyBetter when logic is complex—multiple branches, nested conditions
PerformanceSlightly faster (Python optimizes the internal loop)Slightly slower due to repeated .append() calls
Side effectsNot designed for side effects (printing, file I/O)Ideal when you need to perform actions beyond building a list
DebuggingHarder to set breakpoints inside the expressionEasy to add print statements or breakpoints at each step
Line count1 line3–5 lines

Comparison of list comprehensions and traditional for loops

⚖️

WHEN TO USE WHICH

Use a list comprehension when your goal is to produce a new list from an existing collection with a straightforward transformation or filter. Stick with a for loop when the body is complex, requires multiple statements, or involves side effects like printing or writing to a file. A good rule of thumb: if the comprehension doesn't fit comfortably on one line (roughly 80 characters), use a loop instead.

SECTION 8

Connection to Advanced Concepts

Once you're comfortable with basic list comprehensions, Python offers several related features that build on the same idea. These advanced tools follow the same pattern but apply it to different data structures or more complex scenarios.

This LessonAdvanced VersionKey Difference
[expr for x in lst]{expr for x in lst}Set comprehension — produces a set with unique values (curly braces)
[expr for x in lst]{k: v for k, v in pairs}Dict comprehension — builds a dictionary from key-value pairs
Single for clause[expr for x in a for y in b]Nested comprehension — multiple for clauses act like nested loops
List comprehension(expr for x in lst)Generator expression — uses parentheses and produces items lazily (one at a time) to save memory

How list comprehensions connect to more advanced Python features

You might also encounter the built-in functions map() and filter(), which perform similar tasks. In modern Python, list comprehensions are generally preferred over map() and filter() because they are more readable and don't require wrapping the result in list(). As you advance, learning about generator expressions will help you handle very large datasets efficiently.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

In the list comprehension [x + 1 for x in nums if x > 5], identify the output expression, the loop variable, the iterable, and the filter condition. In what order does Python actually execute these parts?
Show answer
The output expression is x + 1, the loop variable is x, the iterable is nums, and the filter condition is x > 5. Python first iterates over nums, then checks x > 5 for each item, and only then evaluates x + 1 for items that pass the filter. The reading order (expression first) differs from the execution order.

Question 2: BASIC CALCULATION

Write a list comprehension that takes the list temps_c = [0, 20, 37, 100] and converts each Celsius temperature to Fahrenheit using the formula F = C × 9/5 + 32. What is the resulting list?
Show answer
The comprehension is [c * 9/5 + 32 for c in temps_c]. Evaluating each: 0 × 9/5 + 32 = 32.0, 20 × 9/5 + 32 = 68.0, 37 × 9/5 + 32 = 98.6, 100 × 9/5 + 32 = 212.0. The resulting list is [32.0, 68.0, 98.6, 212.0]. This is a pure mapping comprehension with no filter clause.

Question 3: INTERMEDIATE

Given words = ["apple", "Banana", "cherry", "Date", "elderberry"], write a list comprehension that produces a list of lowercased words that have more than 5 characters. What is the result?
Show answer
The comprehension is [w.lower() for w in words if len(w) > 5]. First, we filter: "apple" has 5 characters (not more than 5, so excluded), "Banana" has 6 (included), "cherry" has 6 (included), "Date" has 4 (excluded), "elderberry" has 10 (included). Then we apply .lower() to each passing word. The result is ["banana", "cherry", "elderberry"]. This combines filtering (length check) with mapping (lowercasing).

Question 4: APPLIED

You're building a simple grade tracker. You have a list of tuples representing student names and their scores: students = [("Alice", 92), ("Bob", 58), ("Cara", 85), ("Dan", 44), ("Eve", 76)]. Write a list comprehension that creates a list of strings in the format "Name: score" for only those students who scored 70 or above.
Show answer
The comprehension is [f"{name}: {score}" for name, score in students if score >= 70]. Here we use tuple unpacking in the for clause—for name, score in students automatically assigns the first element to name and the second to score. The result is ["Alice: 92", "Cara: 85", "Eve: 76"]. Bob and Dan are excluded because their scores are below 70.

Question 5: CRITICAL THINKING

A classmate writes the following code to find all two-digit perfect squares: result = [n for n in range(100) if n ** 0.5 == int(n ** 0.5) if n >= 10] This code uses two if clauses. Is this valid Python? Rewrite it in a cleaner way, and explain what the output would be.
Show answer
Yes, multiple if clauses are valid Python—they act like and. However, using floating-point comparison for perfect squares can be unreliable due to rounding. A cleaner approach is [n ** 2 for n in range(4, 10)], which directly generates squares of integers from 4 to 9. This avoids the floating-point issue entirely and is more readable. The output is [16, 25, 36, 49, 64, 81]. This problem illustrates that sometimes rethinking the approach—generating values directly rather than filtering—leads to simpler, more robust comprehensions.

SUMMARY

Summary

Summary

A list comprehension is a concise Python syntax for building a new list by applying an output expression to each item in an iterable source, optionally keeping only items that satisfy a filter condition. The general template is [expression for variable in iterable if condition]. Mapping transforms every element, while filtering selects a subset—and you can combine both in a single expression.

Every list comprehension has an equivalent for-loop form, so you can always convert between the two. Use comprehensions when the logic is simple and your goal is to produce a new list; prefer traditional loops when the body is complex or involves side effects. As you grow as a Python programmer, you'll encounter related tools like set comprehensions, dictionary comprehensions, and generator expressions, all of which follow the same powerful pattern.

Varsity Tutors • Python • List Comprehensions — Use list comprehensions for mapping/filtering (intro-to-standard)