1. What are Comprehensions?
Comprehensions are concise ways to create lists, sets, and dictionaries using a single line of code. They are inspired by mathematical set-builder notation.
The general syntax looks like this:
`[expression for item in iterable if condition]` (for lists)
`{expression for item in iterable if condition}` (for sets)
`{key_expression: value_expression for item in iterable if condition}` (for dictionaries)
-
`expression`: The operation to perform on each `item`.
-
`item`: The loop variable that iterates over the `iterable`.
-
`iterable`: The source collection (list, tuple, string, range, etc.).
-
`if condition` (optional): A filter that includes only items for which the condition is `True`.
2. List Comprehensions: The Most Common
List comprehensions are used to create new lists.
Basic Transformation:
# Traditional loop
squares_loop = []
for i in range(1, 6):
squares_loop.append(i**2)
print(f"Squares (loop): {squares_loop}")
# List comprehension
squares_comprehension = [i**2 for i in range(1, 6)]
print(f"Squares (comprehension): {squares_comprehension}")
Squares (loop): [1, 4, 9, 16, 25]
Squares (comprehension): [1, 4, 9, 16, 25]
Filtering with `if` Clause:
You can add an `if` condition to include only certain elements.
# Traditional loop
even_numbers_loop = []
for i in range(1, 11):
if i % 2 == 0:
even_numbers_loop.append(i)
print(f"Even numbers (loop): {even_numbers_loop}")
# List comprehension with filter
even_numbers_comprehension = [i for i in range(1, 11) if i % 2 == 0]
print(f"Even numbers (comprehension): {even_numbers_comprehension}")
# UdaanPath courses starting with 'P'
udaan_courses = ["Python Basics", "Web Dev", "Data Science", "Project Management"]
python_courses = [course for course in udaan_courses if course.startswith("P")]
print(f"UdaanPath Python Courses: {python_courses}")
Even numbers (loop): [2, 4, 6, 8, 10]
Even numbers (comprehension): [2, 4, 6, 8, 10]
UdaanPath Python Courses: ['Python Basics', 'Project Management']
Conditional Expression (`if-else`):
If you want to apply a different expression based on a condition, the `if-else` goes *before* the `for` loop.
# Assign 'Even' or 'Odd' to numbers
even_odd_list = ["Even" if i % 2 == 0 else "Odd" for i in range(1, 6)]
print(f"Even/Odd list: {even_odd_list}")
# UdaanPath student status: "Passed" if score >= 60, else "Failed"
student_scores = {"Alice": 75, "Bob": 55, "Charlie": 90, "David": 48}
student_results = [f"{name}: {'Passed' if score >= 60 else 'Failed'}"
for name, score in student_scores.items()]
print(f"UdaanPath Student Results: {student_results}")
Even/Odd list: ['Odd', 'Even', 'Odd', 'Even', 'Odd']
UdaanPath Student Results: ['Alice: Passed', 'Bob: Failed', 'Charlie: Passed', 'David: Failed']
Important Distinction:
- `[expression for item in iterable if condition]` : filters elements.
- `[expression_true if condition else expression_false for item in iterable]` : transforms elements conditionally.
Nested List Comprehensions:
You can use multiple `for` clauses to flatten lists or generate combinations.
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened_list = [num for row in matrix for num in row]
print(f"Flattened matrix: {flattened_list}")
# Generate (x, y) coordinates
coordinates = [(x, y) for x in range(1, 3) for y in range(1, 3)]
print(f"Coordinates: {coordinates}")
Flattened matrix: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Coordinates: [(1, 1), (1, 2), (2, 1), (2, 2)]
3. Set Comprehensions: For Unique Collections
Set comprehensions are similar to list comprehensions but use curly braces `{}` and automatically ensure uniqueness of elements.
text = "UdaanPath Python Programming"
unique_chars = {char.lower() for char in text if char.isalpha()}
print(f"Unique characters: {unique_chars}")
numbers = [1, 2, 2, 3, 4, 4, 5]
unique_squares = {x**2 for x in numbers}
print(f"Unique squares: {unique_squares}")
Unique characters: {'u', 'h', 'o', 'a', 'g', 'm', 'r', 't', 'p', 'i', 'y', 'n', 'd', 's', 'c'}
Unique squares: {1, 4, 9, 16, 25}
4. Dictionary Comprehensions: Key-Value Pairs
Dictionary comprehensions are used to create dictionaries, where you specify both a key and a value expression.
# Create a dictionary of number:square pairs
squares_dict = {i: i**2 for i in range(1, 6)}
print(f"Squares dictionary: {squares_dict}")
# Filter products from an inventory
udaan_inventory = {
"Laptop": 1200, "Monitor": 300, "Keyboard": 75,
"Mouse": 25, "Webcam": 500, "Headphones": 150
}
expensive_items = {item: price for item, price in udaan_inventory.items() if price > 100}
print(f"Expensive Udaan items (>100): {expensive_items}")
# Swap keys and values (assuming values are unique and hashable)
swapped_dict = {value: key for key, value in squares_dict.items()}
print(f"Swapped dictionary: {swapped_dict}")
Squares dictionary: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
Expensive Udaan items (>100): {'Laptop': 1200, 'Monitor': 300, 'Webcam': 500, 'Headphones': 150}
Swapped dictionary: {1: 1, 4: 2, 9: 3, 16: 4, 25: 5}
5. Generator Expressions (Brief Mention)
Similar to list comprehensions, but using parentheses `()` instead of square brackets `[]` creates a **generator object**. Generators are memory-efficient as they produce items one by one on demand, rather than building the entire collection in memory at once.
# List comprehension (creates list in memory)
list_comp = [i**2 for i in range(1000000)]
print(f"List comprehension type: {type(list_comp)}")
# Generator expression (creates generator object)
gen_exp = (i**2 for i in range(1000000))
print(f"Generator expression type: {type(gen_exp)}")
# You can iterate over a generator or convert it to a list/tuple
# first_five_squares = list(gen_exp)[:5] # This would consume from the generator
# print(f"First five squares from generator: {first_five_squares}")
List comprehension type: <class 'list'>
Generator expression type: <class 'generator'>
UdaanPath Perspective: For very large datasets, using generator expressions can significantly reduce memory consumption, a crucial consideration for real-world applications. We'll delve deeper into generators in a later module.