Table of Contents

    List Comprehension

    CHAPTER 29.1 · ADVANCED PYTHON FEATURES

    List Comprehension in Python

    Learn how to create, transform, filter, and flatten Python lists using concise and readable list-comprehension syntax.

    Python programmers frequently create a new list by processing the values of an existing iterable. A traditional solution usually requires an empty list, a loop, and one or more calls to append().

    A list comprehension provides a shorter and more expressive way to perform the same operation. It combines an expression, a loop, and an optional condition inside square brackets.

    Learning objective: In this tutorial, you will learn the syntax of list comprehension, how to transform and filter values, how to use conditional expressions, how to work with nested loops, and when a normal loop is a better choice.

    Prerequisites

    What You Should Know

    • Creating and accessing Python lists
    • Using for loops
    • Using if and else conditions
    • Calling functions and methods
    • Using operators such as +, *, %, and comparison operators
    • Basic understanding of iterable objects

    What is List Comprehension?

    List comprehension is a Python syntax for creating a new list by evaluating an expression for each item in an iterable.

    It can optionally include a condition that determines which items should be included in the resulting list.

    Think of it as a processing pipeline

    Values enter from an iterable, an optional condition filters them, an expression transforms the accepted values, and the results are collected into a new list.

    Basic Syntax

    LIST COMPREHENSION SYNTAX
    [expression for item in iterable if condition]

    The condition is optional. Therefore, the simplest form is:

    new_list = [expression for item in iterable]

    The filtering form is:

    new_list = [
        expression
        for item in iterable
        if condition
    ]

    Understanding Each Part

    Part Purpose Example
    Expression Calculates the value added to the new list. number ** 2
    Item Represents the current value during iteration. number
    Iterable Supplies the values to process. numbers
    Condition Optionally filters the input values. number % 2 == 0

    Your First List Comprehension

    Create a new list containing the same values as an existing list:

    numbers = [1, 2, 3, 4, 5]
    
    copied_numbers = [
        number
        for number in numbers
    ]
    
    print(copied_numbers)

    Output:

    [1, 2, 3, 4, 5]

    The expression is number. Therefore, every original value is added to the new list without modification.

    Traditional Loop vs List Comprehension

    Using a Traditional Loop

    numbers = [1, 2, 3, 4, 5]
    squares = []
    
    for number in numbers:
        squares.append(number ** 2)
    
    print(squares)

    Using List Comprehension

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

    Output:

    [1, 4, 9, 16, 25]
    Both examples produce the same result. The comprehension expresses the list-creation operation without manually creating an empty list or calling append().

    Use List Comprehension with range()

    Any iterable can supply values to a list comprehension. The range() function is commonly used for number sequences.

    numbers = [
        number
        for number in range(1, 6)
    ]
    
    print(numbers)

    Output:

    [1, 2, 3, 4, 5]

    Create squares from 1 through 10:

    squares = [
        number ** 2
        for number in range(1, 11)
    ]
    
    print(squares)

    Output:

    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

    Transform List Values

    The expression can modify every value before adding it to the new list.

    Multiply Every Number

    prices = [100, 250, 400]
    
    doubled_prices = [
        price * 2
        for price in prices
    ]
    
    print(doubled_prices)

    Output:

    [200, 500, 800]

    Convert Strings to Uppercase

    names = ["ravi", "amina", "john"]
    
    uppercase_names = [
        name.upper()
        for name in names
    ]
    
    print(uppercase_names)

    Output:

    ['RAVI', 'AMINA', 'JOHN']

    Filter Values with if

    An if condition placed after the iterable acts as a filter. Only values for which the condition is true are processed.

    Create a list containing only even numbers:

    numbers = [1, 2, 3, 4, 5, 6, 7, 8]
    
    even_numbers = [
        number
        for number in numbers
        if number % 2 == 0
    ]
    
    print(even_numbers)

    Output:

    [2, 4, 6, 8]
    FILTERING ORDER
    Read ItemTest ConditionEvaluate ExpressionAdd Result

    Filter String Values

    Select names that begin with the letter A:

    names = [
        "Amina",
        "Rahul",
        "Anita",
        "David",
        "Arif"
    ]
    
    names_starting_with_a = [
        name
        for name in names
        if name.startswith("A")
    ]
    
    print(names_starting_with_a)

    Output:

    ['Amina', 'Anita', 'Arif']

    Filter words whose length is greater than five:

    words = [
        "python",
        "code",
        "developer",
        "list",
        "function"
    ]
    
    long_words = [
        word
        for word in words
        if len(word) > 5
    ]
    
    print(long_words)

    Output:

    ['python', 'developer', 'function']

    Transform and Filter Together

    A comprehension can filter the input and transform the accepted values in the same expression.

    numbers = [1, 2, 3, 4, 5, 6]
    
    even_squares = [
        number ** 2
        for number in numbers
        if number % 2 == 0
    ]
    
    print(even_squares)

    Output:

    [4, 16, 36]

    In this example, odd numbers are rejected. The accepted even numbers are squared before being added to the resulting list.

    Use if-else in the Expression

    An inline conditional expression can produce one value when a condition is true and another value when it is false.

    numbers = [1, 2, 3, 4, 5, 6]
    
    labels = [
        "Even" if number % 2 == 0 else "Odd"
        for number in numbers
    ]
    
    print(labels)

    Output:

    ['Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even']
    When if-else chooses the output value, it appears before the for clause. A filtering if appears after the iterable.

    Filtering if vs Conditional if-else

    Type Purpose Position
    Filtering if Decides whether an input item is included. After the iterable
    Conditional if-else Decides which output value is generated. Before the for clause

    Filtering Example

    result = [
        number
        for number in range(10)
        if number % 2 == 0
    ]

    Conditional Output Example

    result = [
        "Even" if number % 2 == 0 else "Odd"
        for number in range(10)
    ]

    Call a Function in List Comprehension

    The expression may contain a function call.

    def calculate_discount(price):
        return round(price * 0.90, 2)
    
    
    prices = [100, 250, 500]
    
    discounted_prices = [
        calculate_discount(price)
        for price in prices
    ]
    
    print(discounted_prices)

    Output:

    [90.0, 225.0, 450.0]

    Work with a List of Dictionaries

    Consider a list containing employee records:

    employees = [
        {"name": "Amina", "active": True},
        {"name": "Rahul", "active": False},
        {"name": "David", "active": True},
    ]
    
    active_employee_names = [
        employee["name"]
        for employee in employees
        if employee["active"]
    ]
    
    print(active_employee_names)

    Output:

    ['Amina', 'David']

    Use Multiple Conditions

    Combine conditions with logical operators:

    numbers = range(1, 31)
    
    selected_numbers = [
        number
        for number in numbers
        if number % 2 == 0 and number % 3 == 0
    ]
    
    print(selected_numbers)

    Output:

    [6, 12, 18, 24, 30]

    List Comprehension with Nested Loops

    A list comprehension can contain more than one for clause.

    Create coordinate pairs:

    coordinates = [
        (row, column)
        for row in range(1, 3)
        for column in range(1, 4)
    ]
    
    print(coordinates)

    Output:

    [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3)]

    The equivalent traditional loops are:

    coordinates = []
    
    for row in range(1, 3):
        for column in range(1, 4):
            coordinates.append((row, column))
    
    print(coordinates)
    The order of the for clauses in the comprehension follows the order of the equivalent nested loops.

    Flatten a Nested List

    Flattening converts a nested list into one list of values.

    matrix = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ]
    
    flattened = [
        value
        for row in matrix
        for value in row
    ]
    
    print(flattened)

    Output:

    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    Create a Matrix

    A nested comprehension can create a list containing other lists:

    matrix = [
        [
            column
            for column in range(1, 4)
        ]
        for row in range(3)
    ]
    
    print(matrix)

    Output:

    [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
    Readability Warning Deeply nested comprehensions can be difficult to read. Use normal loops when the structure or processing logic becomes complicated.

    Process Characters from a String

    A string is iterable, so its individual characters can be processed.

    text = "Python 3.14"
    
    letters = [
        character.upper()
        for character in text
        if character.isalpha()
    ]
    
    print(letters)

    Output:

    ['P', 'Y', 'T', 'H', 'O', 'N']

    Handle Invalid Input Safely

    Avoid placing complicated exception-handling logic inside a list comprehension. Move that logic into a named function.

    def convert_to_integer(value):
        try:
            return int(value)
        except ValueError:
            return None
    
    
    values = ["10", "25", "invalid", "40"]
    
    converted_values = [
        convert_to_integer(value)
        for value in values
    ]
    
    print(converted_values)

    Output:

    [10, 25, None, 40]

    List Comprehension and Memory

    A list comprehension creates the complete result list in memory. This is appropriate when the resulting list is required for later indexing, repeated iteration, or modification.

    squares = [
        number ** 2
        for number in range(1, 1001)
    ]

    When values need to be processed one at a time rather than stored immediately, a generator expression may be more appropriate:

    square_generator = (
        number ** 2
        for number in range(1, 1001)
    )
    Feature List Comprehension Generator Expression
    Brackets Square brackets Parentheses
    Evaluation Creates the result list immediately Produces values when requested
    Result A list A generator object

    When to Use List Comprehension

    Good Use Cases

    • Creating a list from an existing iterable
    • Applying a simple transformation to every item
    • Filtering values using a short condition
    • Transforming and filtering in one readable expression
    • Flattening a simple nested structure
    • Replacing a short append-based loop

    When Not to Use List Comprehension

    Prefer a Normal Loop When

    • The expression contains complicated business logic.
    • Multiple statements must run for every item.
    • Detailed exception handling is required.
    • Several nested loops make the code difficult to follow.
    • The operation exists mainly for side effects.
    • Debugging requires intermediate values or breakpoints.

    Poor and Readable Comprehensions

    Difficult to Read

    • Multiple nested transformations
    • Several unrelated conditions
    • Unclear single-letter variable names
    • Hidden function side effects
    • Too much logic inside one expression

    Easy to Read

    • One clear transformation
    • One short filtering condition
    • Descriptive variable names
    • Pure expression without side effects
    • Formatting across multiple lines when needed

    Practical Example: Eligible Orders

    Consider a list of customer orders. We want the order numbers for completed orders worth at least 1,000.

    orders = [
        {
            "order_number": "ORD-101",
            "amount": 750,
            "completed": True,
        },
        {
            "order_number": "ORD-102",
            "amount": 1500,
            "completed": True,
        },
        {
            "order_number": "ORD-103",
            "amount": 1800,
            "completed": False,
        },
        {
            "order_number": "ORD-104",
            "amount": 2200,
            "completed": True,
        },
    ]
    
    eligible_order_numbers = [
        order["order_number"]
        for order in orders
        if order["completed"] and order["amount"] >= 1000
    ]
    
    print(eligible_order_numbers)

    Output:

    ['ORD-102', 'ORD-104']

    Common Mistakes

    1

    Incorrect Clause Order

    Incorrect Idea Placing a filtering condition before the for clause.
    Correct Pattern [expression for item in iterable if condition]
    2

    Confusing Filtering with if-else

    Filter Items [item for item in values if condition]
    Choose Output [value_a if condition else value_b for item in values]
    3

    Using append() Inside the Expression

    A comprehension already builds and returns a new list.

    Solution Return the desired value as the expression instead of calling append().
    4

    Creating an Unused List

    Using list comprehension only to call a function for its side effects creates an unnecessary list.

    Solution Use a normal for loop when the result list is not needed.

    Hands-On Practice

    Practice Exercises

    • Create a list containing cubes from 1 through 10.
    • Extract all odd numbers from a list.
    • Convert a collection of names to title case.
    • Select words containing more than six characters.
    • Create labels indicating whether numbers are positive, negative, or zero.
    • Flatten a two-dimensional list.
    • Create coordinate pairs from two ranges.
    • Extract active employee names from a list of dictionaries.

    Knowledge Check

    1

    What does a list comprehension produce?

    It evaluates its expression and collects the resulting values into a new list.

    2

    Is the filtering condition mandatory?

    No. The filtering if condition is optional.

    3

    How do you create squares from 1 through 5?

    squares = [
        number ** 2
        for number in range(1, 6)
    ]
    4

    How do you select only even numbers?

    even_numbers = [
        number
        for number in numbers
        if number % 2 == 0
    ]
    5

    When should a normal loop be preferred?

    Prefer a normal loop when the operation contains complex logic, several statements, detailed exception handling, or significant side effects.

    List Comprehension Quick Reference

    # Copy values
    result = [item for item in iterable]
    
    # Transform values
    result = [transform(item) for item in iterable]
    
    # Filter values
    result = [
        item
        for item in iterable
        if condition
    ]
    
    # Transform and filter
    result = [
        transform(item)
        for item in iterable
        if condition
    ]
    
    # Conditional output
    result = [
        value_if_true if condition else value_if_false
        for item in iterable
    ]
    
    # Nested loops
    result = [
        expression
        for outer_item in outer_iterable
        for inner_item in inner_iterable
    ]
    
    # Flatten nested lists
    flattened = [
        item
        for row in nested_list
        for item in row
    ]

    Summary

    What You Learned

    • List comprehension provides concise syntax for creating new lists.
    • The expression determines the value added to the result.
    • A filtering condition determines which input values are accepted.
    • An inline if-else expression selects between output values.
    • Functions and methods can be called inside the expression.
    • Multiple for clauses can represent nested loops.
    • A comprehension can flatten a simple nested list.
    • Normal loops are preferable when comprehension logic becomes difficult to understand.

    Key Takeaway

    Use list comprehension when a list can be created through a clear transformation, an optional filter, and a readable iteration. If the logic becomes complicated, choose a normal loop to preserve clarity.