0%

Transforming and Combining Data · practice

Readable Comprehensions

The previous lessons built new of scores and checks with ordinary . Those loops are clear, and they remain the right tool when the work has several steps.

When a loop performs one small, predictable transformation, Python offers a shorter form called a comprehension. Start with this familiar loop:

long_titles = []
for lesson in lessons:
    if lesson["minutes"] >= 10:
        long_titles.append(lesson["title"])

A list comprehension expresses the same work in one collection-shaped :

long_titles = [
    lesson["title"]
    for lesson in lessons
    if lesson["minutes"] >= 10
]

Read it as: collect each lesson title for each lesson if its duration is at least ten minutes.

Other comprehension results

A set comprehension keeps unique values:

chapters = {
    lesson["chapter"]
    for lesson in lessons
}

A comprehension creates key- pairs:

minutes_by_title = {
    lesson["title"]: lesson["minutes"]
    for lesson in lessons
}

The braces look similar. A colon creates a dictionary comprehension; a single expression creates a set comprehension.

Prefer clarity over compression

Use a comprehension when it has:

  • one clear output expression;

  • one source collection;

  • at most one simple filter.

Use a normal loop when the work needs several statements, multiple decisions, error handling, or explanatory intermediate names. A comprehension is a readability tool, not a contest to fit the most logic on one line.

Drop the brackets when nothing needs the list

A comprehension builds a whole collection. When that collection is fed straight into sum(), min(), max(), any(), or all(), nothing ever needs it to exist:

Try it

Same answer. The first line builds a two-item list, hands it to sum(), and throws it away. The second supplies the values one at a time without building an intermediate list.

Without the brackets it is called a generator expression, and inside a call like this the parentheses of the call are enough. Prefer it whenever the collection is not the point:

sum(lesson["minutes"] for lesson in lessons)
any(lesson["minutes"] > 15 for lesson in lessons)

Keep the brackets when you actually want the collection: to store it, return it, loop over it twice, or ask for its length.

The saving here is two items and invisible. Over a large collection it is the difference between holding everything in memory and holding one item at a time. Chapter 11 returns to generator expressions and explains why they are lazy.

What does this create?

{lesson["chapter"] for lesson in lessons}

Build three useful views

Complete the function with one list, one set, and one dictionary comprehension.

Task

Complete build_views with three comprehensions.

  • passing_names: learner names for attempts where score >= required.

  • topics: the set of all topic values.

  • scores_by_learner: each learner name mapped to the score.

Return the three collections in the provided . Keep each comprehension readable across multiple lines.