Lab 11: List Comprehensions & Generators

🎯 Objective

Master Python's most powerful iteration tools — list/dict/set comprehensions, generator expressions, and the iterator protocol — for writing concise, memory-efficient code.

📚 Background

Comprehensions are Python's answer to map() and filter() — they express data transformations in a single readable line. Generators produce values lazily (one at a time) instead of building the entire collection in memory first, making them essential for large datasets. Understanding iterators explains how for loops actually work under the hood.

⏱️ Estimated Time

35 minutes

📋 Prerequisites

  • Lab 10: Modules & Packages

🛠️ Tools Used

  • Python 3.12

🔬 Lab Instructions

Step 1: List Comprehensions

📸 Verified Output:

Step 2: Nested Comprehensions

📸 Verified Output:

Step 3: Dict and Set Comprehensions

📸 Verified Output:

Step 4: Generator Expressions

📸 Verified Output:

💡 Generators are 40× smaller in memory than equivalent lists. Use them when processing large datasets — log files, database rows, API pages.

Step 5: Generator Functions (yield)

📸 Verified Output:

Step 6: Infinite Generators

📸 Verified Output:

Step 7: Custom Iterators

📸 Verified Output:

Step 8: Real-World Pipeline with Generators

📸 Verified Output:

✅ Verification

Expected output:

🚨 Common Mistakes

  1. Consuming a generator twice: Generators are one-time iterators — convert to list() if you need to reuse.

  2. Nested comprehensions that are too clever: More than 2 levels of nesting → use a regular loop.

  3. Generator vs list for indexing: gen[0] raises TypeError — generators have no indexing.

  4. Missing yield in generator function: Without yield, the function returns None instead of a generator.

  5. Comprehension side effects: Don't use [print(x) for x in items] — use a regular loop for side effects.

📝 Summary

  • List comprehension: [expr for item in iterable if cond] — concise, creates list

  • Dict comprehension: {k: v for k, v in iterable} — create dicts from data

  • Set comprehension: {expr for item in iterable} — create sets (unique)

  • Generator expression: (expr for ...) — lazy, memory-efficient; use in sum(), max(), any()

  • Generator function: uses yield to produce values one at a time; next() advances

  • Iterator protocol: __iter__() + __next__() — what makes for loops work

🔗 Further Reading

Last updated