Container Comparison and Comprehensive Comprehensions
We've covered lists, tuples, dictionaries, and sets individually. Now let's do a side-by-side comparison — what are the differences, and when should you use each? We'll also thoroughly master comprehensions, one of Python's most powerful features.
1. Four Containers Compared
| Feature | List (list) |
Tuple (tuple) |
Dictionary (dict) |
Set (set) |
|---|---|---|---|---|
| Syntax | [] |
() |
{key: value} |
{} or set() |
| Ordered | ✅ Yes | ✅ Yes | ✅ Insertion order (3.7+) | ❌ Unordered |
| Mutable | ✅ | ❌ | ✅ | ✅ |
| Duplicates | ✅ Allowed | ✅ Allowed | Keys unique, values can repeat | ❌ Unique elements |
| Access | Index [0] |
Index [0] |
Key ["key"] |
No index support |
| Lookup speed | O(n) slow | O(n) slow | O(1) very fast | O(1) very fast |
| Typical use | Ordered data, dynamic collections | Fixed data, function returns | Mappings, caches | Dedup, set operations |
Example: Container Selection Comparison (Difficulty ⭐⭐)
# Same scenario implemented with different containers
# Scenario: storing student names
# List — ordered, easy to add/remove
students_list = ["Alice", "Bob", "Charlie"]
students_list.append("Diana")
print(f"List: {students_list[0]}") # Alice
# Tuple — fixed (like a class roster)
students_tuple = ("Alice", "Bob", "Charlie")
# students_tuple[0] = "xxx" # Error! Tuples are immutable
print(f"Tuple: {students_tuple[0]}") # Alice
# Dictionary — fast lookup by ID
students_dict = {
"001": "Alice",
"002": "Bob",
"003": "Charlie",
}
print(f"Dict: {students_dict['002']}") # Bob — O(1) speed
# Set — deduplication (like an attendance list)
attendance = {"Alice", "Bob", "Charlie", "Alice"}
print(f"Set: {attendance}") # {'Bob', 'Charlie', 'Alice'} — Alice deduplicated
2. Advanced List Comprehensions
Lesson 11 covered basic comprehensions. Let's dive deeper.
Multiple Conditions
numbers = range(1, 31)
# Divisible by 3 AND divisible by 5
filtered = [n for n in numbers if n % 3 == 0 and n % 5 == 0]
print(filtered) # [15, 30]
# Divisible by 3 OR divisible by 5
filtered = [n for n in numbers if n % 3 == 0 or n % 5 == 0]
print(filtered) # [3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24, 25, 27, 30]
Nested Loop Comprehensions
# Generate coordinate pairs — equivalent to double for loop
pairs = [(x, y) for x in range(3) for y in range(3)]
print(pairs)
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
# Nested with condition — find pairs where sum is even
pairs = [(x, y) for x in range(3) for y in range(3) if (x + y) % 2 == 0]
print(pairs)
# [(0, 0), (0, 2), (1, 1), (2, 0), (2, 2)]
if-else in Comprehensions
# if-else in comprehensions — note the different position
numbers = [1, 2, 3, 4, 5, 6]
# Only if (filtering) — placed after
evens = [n for n in numbers if n % 2 == 0]
# if-else (transformation) — placed before
result = ["even" if n % 2 == 0 else "odd" for n in numbers]
print(result) # ['odd', 'even', 'odd', 'even', 'odd', 'even']
Example: Data Transformation Pipeline (Difficulty ⭐⭐⭐)
# One line: filter → transform → format
raw = [" apple ", "BANANA", "", " CHERRY", None, " date "]
# Filter out None and empty strings → strip whitespace → capitalize
cleaned = [item.strip().capitalize() for item in raw if item and item.strip()]
print(cleaned) # ['Apple', 'Banana', 'Cherry', 'Date']
Output:
['Apple', 'Banana', 'Cherry', 'Date']
3. Dictionary Comprehensions
Dictionaries can also use comprehensions. The syntax is similar to lists, but uses {} and specifies key-value pairs:
# Basic dict comprehension
squares = {x: x ** 2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# With condition
even_squares = {x: x ** 2 for x in range(10) if x % 2 == 0}
print(even_squares) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}
# Reverse keys and values
original = {"a": 1, "b": 2, "c": 3}
reversed_dict = {value: key for key, value in original.items()}
print(reversed_dict) # {1: 'a', 2: 'b', 3: 'c'}
Practical: Merge Two Lists into a Dict
# Merge two lists into a dictionary
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
result = {names[i]: scores[i] for i in range(len(names))}
print(result) # {'Alice': 85, 'Bob': 92, 'Charlie': 78}
# Using zip() is more elegant
result = {name: score for name, score in zip(names, scores)}
print(result) # {'Alice': 85, 'Bob': 92, 'Charlie': 78}
4. Set Comprehensions
Set comprehensions use {} with just an expression (no colon) — the difference from dict comprehensions is the presence or absence of a colon:
# Set comprehension — auto-deduplication
numbers = [1, 2, 2, 3, 3, 3, 4, 5, 5]
unique_squares = {x ** 2 for x in numbers}
print(unique_squares) # {1, 4, 9, 16, 25}
# With condition
even_set = {x for x in range(20) if x % 2 == 0}
print(even_set) # {0, 2, 4, 6, 8, 10, 12, 14, 16, 18}
[x for x in ...] is a list — ordered, duplicates allowed. {x: y for x in ...} is a dict — has a colon. {x for x in ...} is a set — no colon, unordered, deduplicated.
Example: Word Analysis (Difficulty ⭐⭐⭐)
# Analyze vocabulary in an article
article = """
Python is great. Python is powerful!
I love Python. JavaScript is also great.
But Python is my favorite.
"""
# Extract all words
words = article.lower().split()
# Deduplicate with set comprehension
unique_words = {word.strip(".!,") for word in words}
print(f"Total words: {len(words)}")
print(f"Unique words: {len(unique_words)}")
print(f"All unique words: {sorted(unique_words)}")
Output:
Total words: 18
Unique words: 10
All unique words: ['also', 'but', 'favorite', 'great', 'is', 'javascript', 'love', 'my', 'python', 'i']
Common Use Cases
- Data cleaning pipeline: List comprehension to filter empty values, strip whitespace, and transform format in one line.
- Dictionary mapping inversion: Dict comprehension to swap keys and values for reverse lookup.
- Deduplication counting: Set comprehension for quick unique element statistics.
- Conditional grouping: if-else comprehensions to split data into two groups (like "pass/fail").
- Coordinate generation: Nested comprehensions for chessboard coordinates, pixel grids, etc.
❓ FAQ
[x for x in range(10)] generate all data at once in memory. Generator expressions (x for x in range(10)) are lazy — one value at a time, saving memory. Use generators for large datasets (tens of thousands+).
⚠️ Q: What if a comprehension has more than two levels of nesting? A: Comprehensions with more than two levels become unreadable. Code like [x for xs in matrix for ys in xs for x in ys] is nearly impossible to understand at a glance. If you need three+ levels, use regular for loops or helper functions.
Q: How do I decide which container to use? A: Three questions: ① Do you need unique keys? → dictionary. ② Do you need dedup or set operations? → set. ③ Does data need to change? → list if yes, tuple if no. In most scenarios, lists and dictionaries cover 90% of use cases.📖 Summary
- Lists are ordered and mutable; tuples are ordered and immutable; dicts are key-value with fast lookup; sets are for dedup and math operations
- List comprehension:
[expression for variable in iterable if condition] - Dict comprehension:
{key: value for variable in iterable if condition} - Set comprehension:
{expression for variable in iterable if condition} ifafter the loop is for filtering;if-elsebefore the loop is for transformation- Nested comprehensions can generate 2D data, but more than two levels calls for regular loops
📝 Exercises
-
Basic (Difficulty ⭐): Use a list comprehension to generate all numbers between 10 and 50 that are divisible by 7 or contain the digit 7. Hint: Use
orto combine two conditions. -
Intermediate (Difficulty ⭐⭐): Given two lists
keys = ["name", "age", "city"]andvalues = ["Alice", 25, "Beijing"], use a dict comprehension to merge them into a dict. Hint: Usezip(keys, values)to pair them. -
Challenge (Difficulty ⭐⭐⭐): Write a "data analyzer." Given a string containing multiple sentences, count and output: total word count, unique word count, and the 3 most frequent words. Hint: Use
split()for tokenization, a dictionary for counting, andsorted(dict.items(), key=lambda x: x[1], reverse=True)[:3]for the top 3.



