You need to create a lookup table mapping names to ages. A loop and dict build-up works, but {name: age for name, age in pairs} does it in one line. Dict comprehensions are the idiomatic way to build dictionaries from iterables.

Basic key-value creation

Create a dictionary from a sequence.

word2
basic.py
Replay: real traced execution (multi-file project)
# Basic Dictionary Comprehension

print("=== Basic Dictionary Comprehension ===\n")

# Traditional loop approach
squares_loop = {}
for x in range(1, 6):
    squares_loop[x] = x ** 2
print(f"Loop: {squares_loop}")

# Dictionary comprehension
squares_comp = {x: x ** 2 for x in range(1, 6)}
print(f"Comprehension: {squares_comp}")

print("\n=== Key: Value Structure ===")

# Number to its word
num_words = {1: "one", 2: "two", 3: "three"}
print(f"Manual: {num_words}")

# Same pattern with comprehension
words = ["zero", "one", "two", "three", "four"]
num_to_word = {i: words[i] for i in range(len(words))}
print(f"Comprehension: {num_to_word}")

print("\n=== From Strings ===")

# Character positions
word = "hello"
char_positions = {char: i for i, char in enumerate(word)}
print(f"'{word}' char positions: {char_positions}")

# Note: duplicate chars get last position
word2 = "banana"
char_pos2 = {char: i for i, char in enumerate(word2)}
print(f"'{word2}' char positions: {char_pos2}")

print("\n=== From Other Collections ===")

# Set to length mapping
names = {"Alice", "Bob", "Charlie"}
name_lengths = {name: len(name) for name in names}
print(f"Names: {names}")
print(f"Lengths: {name_lengths}")

print("\n=== Syntax Summary ===")
print("{key_expr: value_expr for item in iterable}")
print(" ^^^^^^^^  ^^^^^^^^^^     ^^^^    ^^^^^^^^")
print(" key       value          var     source")
# Basic Dictionary Comprehension

print("=== Basic Dictionary Comprehension ===\n")

# Traditional loop approach
squares_loop = {}
for x in range(1, 6):
    squares_loop[x] = x ** 2
print(f"Loop: {squares_loop}")

# Dictionary comprehension
squares_comp = {x: x ** 2 for x in range(1, 6)}
print(f"Comprehension: {squares_comp}")

print("\n=== Key: Value Structure ===")

# Number to its word
num_words = {1: "one", 2: "two", 3: "three"}
print(f"Manual: {num_words}")

# Same pattern with comprehension
words = ["zero", "one", "two", "three", "four"]
num_to_word = {i: words[i] for i in range(len(words))}
print(f"Comprehension: {num_to_word}")

print("\n=== From Strings ===")

# Character positions
word = "hello"
char_positions = {char: i for i, char in enumerate(word)}
print(f"'{word}' char positions: {char_positions}")

# Note: duplicate chars get last position
word2 = "abracadabra"
char_pos2 = {char: i for i, char in enumerate(word2)}
print(f"'{word2}' char positions: {char_pos2}")

print("\n=== From Other Collections ===")

# Set to length mapping
names = {"Alice", "Bob", "Charlie"}
name_lengths = {name: len(name) for name in names}
print(f"Names: {names}")
print(f"Lengths: {name_lengths}")

print("\n=== Syntax Summary ===")
print("{key_expr: value_expr for item in iterable}")
print(" ^^^^^^^^  ^^^^^^^^^^     ^^^^    ^^^^^^^^")
print(" key       value          var     source")
# Basic Dictionary Comprehension

print("=== Basic Dictionary Comprehension ===\n")

# Traditional loop approach
squares_loop = {}
for x in range(1, 6):
    squares_loop[x] = x ** 2
print(f"Loop: {squares_loop}")

# Dictionary comprehension
squares_comp = {x: x ** 2 for x in range(1, 6)}
print(f"Comprehension: {squares_comp}")

print("\n=== Key: Value Structure ===")

# Number to its word
num_words = {1: "one", 2: "two", 3: "three"}
print(f"Manual: {num_words}")

# Same pattern with comprehension
words = ["zero", "one", "two", "three", "four"]
num_to_word = {i: words[i] for i in range(len(words))}
print(f"Comprehension: {num_to_word}")

print("\n=== From Strings ===")

# Character positions
word = "hello"
char_positions = {char: i for i, char in enumerate(word)}
print(f"'{word}' char positions: {char_positions}")

# Note: duplicate chars get last position
word2 = "committee"
char_pos2 = {char: i for i, char in enumerate(word2)}
print(f"'{word2}' char positions: {char_pos2}")

print("\n=== From Other Collections ===")

# Set to length mapping
names = {"Alice", "Bob", "Charlie"}
name_lengths = {name: len(name) for name in names}
print(f"Names: {names}")
print(f"Lengths: {name_lengths}")

print("\n=== Syntax Summary ===")
print("{key_expr: value_expr for item in iterable}")
print(" ^^^^^^^^  ^^^^^^^^^^     ^^^^    ^^^^^^^^")
print(" key       value          var     source")
  1. squares_loop ← {}

    3print("=== Basic Dictionary Comprehension ===\n")45# Traditional loop approach  #?traditional6squares_loop→ {} = {}7for x in range(1, 6):
    output=== Basic Dictionary Comprehension ===
  2. squares_loop[x] ← 1

    pass 1 of 5
    6squares_loop = {}7for x1 in range(1, 6):8    squares_loop[x]→ 1 = x1 ** 29print(f"Loop: {squares_loop}")
    All 5 passes — pass 1 is the card above
    passxsquares_loop[x]
    111
    224
    339
    4416
    5525
  3. squares_comp ← {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}, num_words ← {1: 'one', 2: 'two', 3: 'three'}

    8    squares_loop[x] = x ** 29print(f"Loop: {squares_loop{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}}")1011# Dictionary comprehension  #?comprehension12squares_comp→ {1: 1, 2: 4, 3: 9, 4: 16, 5: 25} = {x: x ** 2 for x in range(1, 6)}  #?dictcomp13print(f"Comprehension: {squares_comp{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}}")1415print("\n=== Key: Value Structure ===")1617# Number to its word  #?numword18num_words→ {1: 'one', 2: 'two', 3: 'three'} = {1: "one", 2: "two", 3: "three"}19print(f"Manual: {num_words{1: 'one', 2: 'two', 3: 'three'}}")2021# Same pattern with comprehension22words→ ['zero', 'one', 'two', 'three', 'four'] = ["zero", "one", "two", "three", "four"]23num_to_word→ {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'} = {i: words[i](empty) for i in range(len(words['zero', 'one', 'two', 'three', 'four']))}  #?indexword24print(f"Comprehension: {num_to_word{0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'}}")2526print("\n=== From Strings ===")2728# Character positions  #?charpos29word→ hello = "hello"30char_positions→ {'h': 0, 'e': 1, 'l': 3, 'o': 4} = {char(empty): i(empty) for i, char in enumerate(wordhello)}  #?enumerate31print(f"'{wordhello}' char positions: {char_positions{'h': 0, 'e': 1, 'l': 3, 'o': 4}}")3233# Note: duplicate chars get last position34word2→ banana = "banana"  #@word2="abracadabra", "committee"35char_pos2→ {'b': 0, 'a': 5, 'n': 4} = {char(empty): i(empty) for i, char in enumerate(word2banana)}36print(f"'{word2banana}' char positions: {char_pos2{'b': 0, 'a': 5, 'n': 4}}")3738print("\n=== From Other Collections ===")3940# Set to length mapping  #?setmap41names→ {'Charlie', 'Alice', 'Bob'} = {"Alice", "Bob", "Charlie"}42name_lengths→ {'Charlie': 7, 'Alice': 5, 'Bob': 3} = {name: len(name) for name in names{'Charlie', 'Alice', 'Bob'}}  #?namelen43print(f"Names: {names{'Charlie', 'Alice', 'Bob'}}")44print(f"Lengths: {name_lengths{'Charlie': 7, 'Alice': 5, 'Bob': 3}}")4546print("\n=== Syntax Summary ===")47print("{key_expr: value_expr for item in iterable}")48print(" ^^^^^^^^  ^^^^^^^^^^     ^^^^    ^^^^^^^^")49print(" key       value          var     source")50#@help traditional
    outputLoop: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
    Comprehension: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
    
    === Key: Value Structure ===
    Manual: {1: 'one', 2: 'two', 3: 'three'}
    Comprehension: {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'}
    
    === From Strings ===
    'hello' char positions: {'h': 0, 'e': 1, 'l': 3, 'o': 4}
    'banana' char positions: {'b': 0, 'a': 5, 'n': 4}
    
    === From Other Collections ===
    Names: {'Charlie', 'Alice', 'Bob'}
    Lengths: {'Charlie': 7, 'Alice': 5, 'Bob': 3}
    
    === Syntax Summary ===
    {key_expr: value_expr for item in iterable}
     ^^^^^^^^  ^^^^^^^^^^     ^^^^    ^^^^^^^^
     key       value          var     source
  1. squares_loop ← {}

    3print("=== Basic Dictionary Comprehension ===\n")45# Traditional loop approach6squares_loop→ {} = {}7for x in range(1, 6):
    output=== Basic Dictionary Comprehension ===
  2. squares_loop[x] ← 1

    pass 1 of 5
    6squares_loop = {}7for x1 in range(1, 6):8    squares_loop[x]→ 1 = x1 ** 29print(f"Loop: {squares_loop}")
    All 5 passes — pass 1 is the card above
    passxsquares_loop[x]
    111
    224
    339
    4416
    5525
  3. squares_comp ← {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}, num_words ← {1: 'one', 2: 'two', 3: 'three'}

    8    squares_loop[x] = x ** 29print(f"Loop: {squares_loop{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}}")1011# Dictionary comprehension12squares_comp→ {1: 1, 2: 4, 3: 9, 4: 16, 5: 25} = {x: x ** 2 for x in range(1, 6)}13print(f"Comprehension: {squares_comp{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}}")1415print("\n=== Key: Value Structure ===")1617# Number to its word18num_words→ {1: 'one', 2: 'two', 3: 'three'} = {1: "one", 2: "two", 3: "three"}19print(f"Manual: {num_words{1: 'one', 2: 'two', 3: 'three'}}")2021# Same pattern with comprehension22words→ ['zero', 'one', 'two', 'three', 'four'] = ["zero", "one", "two", "three", "four"]23num_to_word→ {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'} = {i: words[i](empty) for i in range(len(words['zero', 'one', 'two', 'three', 'four']))}24print(f"Comprehension: {num_to_word{0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'}}")2526print("\n=== From Strings ===")2728# Character positions29word→ hello = "hello"30char_positions→ {'h': 0, 'e': 1, 'l': 3, 'o': 4} = {char(empty): i(empty) for i, char in enumerate(wordhello)}31print(f"'{wordhello}' char positions: {char_positions{'h': 0, 'e': 1, 'l': 3, 'o': 4}}")3233# Note: duplicate chars get last position34word2→ abracadabra = "abracadabra"35char_pos2→ {'a': 10, 'b': 8, 'r': 9, 'c': 4, 'd': 6} = {char(empty): i(empty) for i, char in enumerate(word2abracadabra)}36print(f"'{word2abracadabra}' char positions: {char_pos2{'a': 10, 'b': 8, 'r': 9, 'c': 4, 'd': 6}}")3738print("\n=== From Other Collections ===")3940# Set to length mapping41names→ {'Alice', 'Bob', 'Charlie'} = {"Alice", "Bob", "Charlie"}42name_lengths→ {'Alice': 5, 'Bob': 3, 'Charlie': 7} = {name: len(name) for name in names{'Alice', 'Bob', 'Charlie'}}43print(f"Names: {names{'Alice', 'Bob', 'Charlie'}}")44print(f"Lengths: {name_lengths{'Alice': 5, 'Bob': 3, 'Charlie': 7}}")4546print("\n=== Syntax Summary ===")47print("{key_expr: value_expr for item in iterable}")48print(" ^^^^^^^^  ^^^^^^^^^^     ^^^^    ^^^^^^^^")49print(" key       value          var     source")
    outputLoop: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
    Comprehension: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
    
    === Key: Value Structure ===
    Manual: {1: 'one', 2: 'two', 3: 'three'}
    Comprehension: {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'}
    
    === From Strings ===
    'hello' char positions: {'h': 0, 'e': 1, 'l': 3, 'o': 4}
    'abracadabra' char positions: {'a': 10, 'b': 8, 'r': 9, 'c': 4, 'd': 6}
    
    === From Other Collections ===
    Names: {'Alice', 'Bob', 'Charlie'}
    Lengths: {'Alice': 5, 'Bob': 3, 'Charlie': 7}
    
    === Syntax Summary ===
    {key_expr: value_expr for item in iterable}
     ^^^^^^^^  ^^^^^^^^^^     ^^^^    ^^^^^^^^
     key       value          var     source
  1. squares_loop ← {}

    3print("=== Basic Dictionary Comprehension ===\n")45# Traditional loop approach6squares_loop→ {} = {}7for x in range(1, 6):
    output=== Basic Dictionary Comprehension ===
  2. squares_loop[x] ← 1

    pass 1 of 5
    6squares_loop = {}7for x1 in range(1, 6):8    squares_loop[x]→ 1 = x1 ** 29print(f"Loop: {squares_loop}")
    All 5 passes — pass 1 is the card above
    passxsquares_loop[x]
    111
    224
    339
    4416
    5525
  3. squares_comp ← {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}, num_words ← {1: 'one', 2: 'two', 3: 'three'}

    8    squares_loop[x] = x ** 29print(f"Loop: {squares_loop{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}}")1011# Dictionary comprehension12squares_comp→ {1: 1, 2: 4, 3: 9, 4: 16, 5: 25} = {x: x ** 2 for x in range(1, 6)}13print(f"Comprehension: {squares_comp{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}}")1415print("\n=== Key: Value Structure ===")1617# Number to its word18num_words→ {1: 'one', 2: 'two', 3: 'three'} = {1: "one", 2: "two", 3: "three"}19print(f"Manual: {num_words{1: 'one', 2: 'two', 3: 'three'}}")2021# Same pattern with comprehension22words→ ['zero', 'one', 'two', 'three', 'four'] = ["zero", "one", "two", "three", "four"]23num_to_word→ {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'} = {i: words[i](empty) for i in range(len(words['zero', 'one', 'two', 'three', 'four']))}24print(f"Comprehension: {num_to_word{0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'}}")2526print("\n=== From Strings ===")2728# Character positions29word→ hello = "hello"30char_positions→ {'h': 0, 'e': 1, 'l': 3, 'o': 4} = {char(empty): i(empty) for i, char in enumerate(wordhello)}31print(f"'{wordhello}' char positions: {char_positions{'h': 0, 'e': 1, 'l': 3, 'o': 4}}")3233# Note: duplicate chars get last position34word2→ committee = "committee"35char_pos2→ {'c': 0, 'o': 1, 'm': 3, 'i': 4, 't': 6, 'e': 8} = {char(empty): i(empty) for i, char in enumerate(word2committee)}36print(f"'{word2committee}' char positions: {char_pos2{'c': 0, 'o': 1, 'm': 3, 'i': 4, 't': 6, 'e': 8}}")3738print("\n=== From Other Collections ===")3940# Set to length mapping41names→ {'Alice', 'Charlie', 'Bob'} = {"Alice", "Bob", "Charlie"}42name_lengths→ {'Alice': 5, 'Charlie': 7, 'Bob': 3} = {name: len(name) for name in names{'Alice', 'Charlie', 'Bob'}}43print(f"Names: {names{'Alice', 'Charlie', 'Bob'}}")44print(f"Lengths: {name_lengths{'Alice': 5, 'Charlie': 7, 'Bob': 3}}")4546print("\n=== Syntax Summary ===")47print("{key_expr: value_expr for item in iterable}")48print(" ^^^^^^^^  ^^^^^^^^^^     ^^^^    ^^^^^^^^")49print(" key       value          var     source")
    outputLoop: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
    Comprehension: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
    
    === Key: Value Structure ===
    Manual: {1: 'one', 2: 'two', 3: 'three'}
    Comprehension: {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'}
    
    === From Strings ===
    'hello' char positions: {'h': 0, 'e': 1, 'l': 3, 'o': 4}
    'committee' char positions: {'c': 0, 'o': 1, 'm': 3, 'i': 4, 't': 6, 'e': 8}
    
    === From Other Collections ===
    Names: {'Alice', 'Charlie', 'Bob'}
    Lengths: {'Alice': 5, 'Charlie': 7, 'Bob': 3}
    
    === Syntax Summary ===
    {key_expr: value_expr for item in iterable}
     ^^^^^^^^  ^^^^^^^^^^     ^^^^    ^^^^^^^^
     key       value          var     source

{key: value for item in iterable} - define both key and value.

dict comprehension Concise dict creation: `{k: v for k, v in items}`. Replaces loop + assignment.

From parallel lists

Combine two lists into a dictionary.

from_lists.py
Replay: real traced execution (multi-file project)
# Dictionary from Parallel Lists

print("=== Creating Dict from Two Lists ===\n")

# Two parallel lists
keys = ["name", "age", "city"]
values = ["Alice", 30, "NYC"]
print(f"Keys: {keys}")
print(f"Values: {values}")

# Using zip() with dict comprehension
person = {k: v for k, v in zip(keys, values)}
print(f"Dict: {person}")

# Shortcut: dict() constructor
person2 = dict(zip(keys, values))
print(f"dict(zip()): {person2}")

print("\n=== Multiple Records ===")

# Employee data as parallel lists
ids = [101, 102, 103]
names = ["Alice", "Bob", "Charlie"]
salaries = [50000, 60000, 55000]

# ID to name mapping
id_to_name = {i: n for i, n in zip(ids, names)}
print(f"ID → Name: {id_to_name}")

# ID to (name, salary) tuple
id_to_info = {i: (n, s) for i, n, s in zip(ids, names, salaries)}
print(f"ID → Info: {id_to_info}")

print("\n=== Index-Based Keys ===")

fruits = ["apple", "banana", "cherry"]

# Index as key
indexed = {i: fruit for i, fruit in enumerate(fruits)}
print(f"Indexed: {indexed}")

# Starting from 1
indexed_from_1 = {i: fruit for i, fruit in enumerate(fruits, start=1)}
print(f"From 1: {indexed_from_1}")

print("\n=== Unequal Lengths ===")

short = [1, 2]
long = ['a', 'b', 'c', 'd']

# zip stops at shorter
result = {k: v for k, v in zip(short, long)}
print(f"short={short}, long={long}")
print(f"zip result: {result}")
  1. keys ← ['name', 'age', 'city'], values ← ['Alice', 30, 'NYC']

    3print("=== Creating Dict from Two Lists ===\n")45# Two parallel lists  #?parallel6keys→ ['name', 'age', 'city'] = ["name", "age", "city"]7values→ ['Alice', 30, 'NYC'] = ["Alice", 30, "NYC"]8print(f"Keys: {keys['name', 'age', 'city']}")9print(f"Values: {values['Alice', 30, 'NYC']}")1011# Using zip() with dict comprehension  #?zipdict12person→ {'name': 'Alice', 'age': 30, 'city': 'NYC'} = {k(empty): v(empty) for k, v in zip(keys['name', 'age', 'city'], values['Alice', 30, 'NYC'])}  #?zipcomp13print(f"Dict: {person{'name': 'Alice', 'age': 30, 'city': 'NYC'}}")1415# Shortcut: dict() constructor  #?dictctr16person2→ {'name': 'Alice', 'age': 30, 'city': 'NYC'} = dict(zip(keys['name', 'age', 'city'], values['Alice', 30, 'NYC']))17print(f"dict(zip()): {person2{'name': 'Alice', 'age': 30, 'city': 'NYC'}}")1819print("\n=== Multiple Records ===")2021# Employee data as parallel lists  #?employees22ids→ [101, 102, 103] = [101, 102, 103]23names→ ['Alice', 'Bob', 'Charlie'] = ["Alice", "Bob", "Charlie"]24salaries→ [50000, 60000, 55000] = [50000, 60000, 55000]2526# ID to name mapping  #?idname27id_to_name→ {101: 'Alice', 102: 'Bob', 103: 'Charlie'} = {i(empty): n(empty) for i, n in zip(ids[101, 102, 103], names['Alice', 'Bob', 'Charlie'])}28print(f"ID → Name: {id_to_name{101: 'Alice', 102: 'Bob', 103: 'Charlie'}}")2930# ID to (name, salary) tuple  #?tuple31id_to_info→ {101: ('Alice', 50000), 102: ('Bob', 60000), 103: ('Charlie', 55000)} = {i(empty): (n(empty), s(empty)) for i, n, s in zip(ids[101, 102, 103], names['Alice', 'Bob', 'Charlie'], salaries[50000, 60000, 55000])}  #?zip332print(f"ID → Info: {id_to_info{101: ('Alice', 50000), 102: ('Bob', 60000), 103: ('Charlie', 55000)}}")3334print("\n=== Index-Based Keys ===")3536fruits→ ['apple', 'banana', 'cherry'] = ["apple", "banana", "cherry"]  #?index3738# Index as key  #?enumdict39indexed→ {0: 'apple', 1: 'banana', 2: 'cherry'} = {i(empty): fruit(empty) for i, fruit in enumerate(fruits['apple', 'banana', 'cherry'])}40print(f"Indexed: {indexed{0: 'apple', 1: 'banana', 2: 'cherry'}}")4142# Starting from 1  #?start143indexed_from_1→ {1: 'apple', 2: 'banana', 3: 'cherry'} = {i(empty): fruit(empty) for i, fruit in enumerate(fruits['apple', 'banana', 'cherry'], start=1)}44print(f"From 1: {indexed_from_1{1: 'apple', 2: 'banana', 3: 'cherry'}}")4546print("\n=== Unequal Lengths ===")4748short→ [1, 2] = [1, 2]49long→ ['a', 'b', 'c', 'd'] = ['a', 'b', 'c', 'd']  #?unequal5051# zip stops at shorter  #?zipstop52result→ {1: 'a', 2: 'b'} = {k(empty): v(empty) for k, v in zip(short[1, 2], long['a', 'b', 'c', 'd'])}53print(f"short={short[1, 2]}, long={long['a', 'b', 'c', 'd']}")54print(f"zip result: {result{1: 'a', 2: 'b'}}")55#@help parallel
    output=== Creating Dict from Two Lists ===
    Keys: ['name', 'age', 'city']
    Values: ['Alice', 30, 'NYC']
    Dict: {'name': 'Alice', 'age': 30, 'city': 'NYC'}
    dict(zip()): {'name': 'Alice', 'age': 30, 'city': 'NYC'}
    
    === Multiple Records ===
    ID → Name: {101: 'Alice', 102: 'Bob', 103: 'Charlie'}
    ID → Info: {101: ('Alice', 50000), 102: ('Bob', 60000), 103: ('Charlie', 55000)}
    
    === Index-Based Keys ===
    Indexed: {0: 'apple', 1: 'banana', 2: 'cherry'}
    From 1: {1: 'apple', 2: 'banana', 3: 'cherry'}
    
    === Unequal Lengths ===
    short=[1, 2], long=['a', 'b', 'c', 'd']
    zip result: {1: 'a', 2: 'b'}

Use zip() to pair up keys and values: {k: v for k, v in zip(keys, values)}.

Filter entries

Include only certain key-value pairs.

filter.py
Replay: real traced execution (multi-file project)
# Filtering in Dictionary Comprehension

print("=== Filtering Dictionary Items ===\n")

# Original dictionary
prices = {"apple": 1.50, "banana": 0.75, "cherry": 3.00, "date": 2.25, "elderberry": 4.50}
print(f"All prices: {prices}")

# Filter by value: expensive items (> $2)
expensive = {k: v for k, v in prices.items() if v > 2.00}
print(f"Expensive (>$2): {expensive}")

# Filter by key: names starting with vowel
vowel_fruits = {k: v for k, v in prices.items() if k[0] in 'aeiou'}
print(f"Vowel start: {vowel_fruits}")

print("\n=== Filtering from Source Dict ===")

scores = {"Alice": 85, "Bob": 92, "Charlie": 78, "Diana": 95, "Eve": 65}
print(f"All scores: {scores}")

# Passing students (>= 70)
passing = {name: score for name, score in scores.items() if score >= 70}
print(f"Passing: {passing}")

# Top performers (>= 90)
top = {name: score for name, score in scores.items() if score >= 90}
print(f"Top (>=90): {top}")

print("\n=== Multiple Conditions ===")

products = {
    "laptop": {"price": 999, "stock": 5},
    "phone": {"price": 699, "stock": 0},
    "tablet": {"price": 399, "stock": 10},
    "watch": {"price": 299, "stock": 3},
}

# In stock AND affordable (< $500)
available_affordable = {
    name: info
    for name, info in products.items()
    if info["stock"] > 0 and info["price"] < 500
}
print(f"Available & <$500: {available_affordable}")

print("\n=== Filtering with External Data ===")

# Keep only selected keys
all_data = {"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}
keep = {"a", "c", "e"}

filtered = {k: v for k, v in all_data.items() if k in keep}
print(f"All: {all_data}")
print(f"Keep {keep}: {filtered}")
  1. prices ← {'apple': 1.5, 'banana': 0.75, 'cherry': 3.0, 'date': 2.25, 'elderberry': 4.5}

    3print("=== Filtering Dictionary Items ===\n")45# Original dictionary  #?original6prices→ {'apple': 1.5, 'banana': 0.75, 'cherry': 3.0, 'date': 2.25, 'elderberry': 4.5} = {"apple": 1.50, "banana": 0.75, "cherry": 3.00, "date": 2.25, "elderberry": 4.50}7print(f"All prices: {prices{'apple': 1.5, 'banana': 0.75, 'cherry': 3.0, 'date': 2.25, 'elderberry': 4.5}}")89# Filter by value: expensive items (> $2)  #?byvalue10expensive→ {'cherry': 3.0, 'date': 2.25, 'elderberry': 4.5} = {k(empty): v(empty) for k, v in prices{'apple': 1.5, 'banana': 0.75, 'cherry': 3.0, 'date': 2.25, 'elderberry': 4.5}.items() if v > 2.00}  #?filtervalue11print(f"Expensive (>$2): {expensive{'cherry': 3.0, 'date': 2.25, 'elderberry': 4.5}}")1213# Filter by key: names starting with vowel  #?bykey14vowel_fruits→ {'apple': 1.5, 'elderberry': 4.5} = {k(empty): v(empty) for k, v in prices{'apple': 1.5, 'banana': 0.75, 'cherry': 3.0, 'date': 2.25, 'elderberry': 4.5}.items() if k[0](empty) in 'aeiou'}  #?filterkey15print(f"Vowel start: {vowel_fruits{'apple': 1.5, 'elderberry': 4.5}}")1617print("\n=== Filtering from Source Dict ===")1819scores→ {'Alice': 85, 'Bob': 92, 'Charlie': 78, 'Diana': 95, 'Eve': 65} = {"Alice": 85, "Bob": 92, "Charlie": 78, "Diana": 95, "Eve": 65}  #?scores20print(f"All scores: {scores{'Alice': 85, 'Bob': 92, 'Charlie': 78, 'Diana': 95, 'Eve': 65}}")2122# Passing students (>= 70)  #?passing23passing→ {'Alice': 85, 'Bob': 92, 'Charlie': 78, 'Diana': 95} = {name(empty): score(empty) for name, score in scores{'Alice': 85, 'Bob': 92, 'Charlie': 78, 'Diana': 95, 'Eve': 65}.items() if score >= 70}24print(f"Passing: {passing{'Alice': 85, 'Bob': 92, 'Charlie': 78, 'Diana': 95}}")2526# Top performers (>= 90)27top→ {'Bob': 92, 'Diana': 95} = {name(empty): score(empty) for name, score in scores{'Alice': 85, 'Bob': 92, 'Charlie': 78, 'Diana': 95, 'Eve': 65}.items() if score >= 90}28print(f"Top (>=90): {top{'Bob': 92, 'Diana': 95}}")2930print("\n=== Multiple Conditions ===")3132products→ {'laptop': {'price': 999, 'stock': 5}, 'phone': {'price': 699, 'stock': 0}, 'tablet': {'price': 399, 'stock': 10}, 'watch': {'price': 299, 'stock': 3}} = {33    "laptop": {"price": 999, "stock": 5},34    "phone": {"price": 699, "stock": 0},35    "tablet": {"price": 399, "stock": 10},36    "watch": {"price": 299, "stock": 3},37}  #?products3839# In stock AND affordable (< $500)  #?multiple40available_affordable→ {'tablet': {'price': 399, 'stock': 10}, 'watch': {'price': 299, 'stock': 3}} = {41    name(empty): info(empty) 42    for name(empty), info(empty) in products{'laptop': {'price': 999, 'stock': 5}, 'phone': {'price': 699, 'stock': 0}, 'tablet': {'price': 399, 'stock': 10}, 'watch': {'price': 299, 'stock': 3}}.items() 43    if info["stock"](empty) > 0 and info["price"](empty) < 50044}  #?multifilter45print(f"Available & <$500: {available_affordable{'tablet': {'price': 399, 'stock': 10}, 'watch': {'price': 299, 'stock': 3}}}")4647print("\n=== Filtering with External Data ===")4849# Keep only selected keys  #?selected50all_data→ {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5} = {"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}51keep→ {'a', 'c', 'e'} = {"a", "c", "e"}5253filtered→ {'a': 1, 'c': 3, 'e': 5} = {k(empty): v(empty) for k, v in all_data{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}.items() if k in keep{'a', 'c', 'e'}}  #?keeponly54print(f"All: {all_data{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}}")55print(f"Keep {keep{'a', 'c', 'e'}}: {filtered{'a': 1, 'c': 3, 'e': 5}}")56#@help original
    output=== Filtering Dictionary Items ===
    All prices: {'apple': 1.5, 'banana': 0.75, 'cherry': 3.0, 'date': 2.25, 'elderberry': 4.5}
    Expensive (>$2): {'cherry': 3.0, 'date': 2.25, 'elderberry': 4.5}
    Vowel start: {'apple': 1.5, 'elderberry': 4.5}
    
    === Filtering from Source Dict ===
    All scores: {'Alice': 85, 'Bob': 92, 'Charlie': 78, 'Diana': 95, 'Eve': 65}
    Passing: {'Alice': 85, 'Bob': 92, 'Charlie': 78, 'Diana': 95}
    Top (>=90): {'Bob': 92, 'Diana': 95}
    
    === Multiple Conditions ===
    Available & <$500: {'tablet': {'price': 399, 'stock': 10}, 'watch': {'price': 299, 'stock': 3}}
    
    === Filtering with External Data ===
    All: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
    Keep {'a', 'c', 'e'}: {'a': 1, 'c': 3, 'e': 5}

Add if condition to filter: {k: v for k, v in items if v > 0}.

Transform keys and values

Modify keys, values, or both.

transform.py
Replay: real traced execution (multi-file project)
# Transforming Keys and Values

print("=== Transforming Values ===\n")

# Original prices
prices = {"apple": 1.50, "banana": 0.75, "cherry": 3.00}
print(f"Original: {prices}")

# Apply 10% discount
discounted = {k: round(v * 0.9, 2) for k, v in prices.items()}
print(f"10% off: {discounted}")

# Convert to cents
cents = {k: int(v * 100) for k, v in prices.items()}
print(f"In cents: {cents}")

print("\n=== Transforming Keys ===")

# Original with lowercase keys
data = {"name": "Alice", "age": 30, "city": "NYC"}
print(f"Original: {data}")

# Uppercase keys
upper_keys = {k.upper(): v for k, v in data.items()}
print(f"Upper keys: {upper_keys}")

# Add prefix to keys
prefixed = {f"user_{k}": v for k, v in data.items()}
print(f"Prefixed: {prefixed}")

print("\n=== Transform Both ===")

raw_scores = {"alice": "85", "bob": "92", "charlie": "78"}
print(f"Raw: {raw_scores}")

# Capitalize names, convert scores to int
clean_scores = {name.capitalize(): int(score) for name, score in raw_scores.items()}
print(f"Clean: {clean_scores}")

print("\n=== Conditional Transform ===")

numbers = {"a": -3, "b": 5, "c": -1, "d": 8}
print(f"Numbers: {numbers}")

# Absolute values
absolute = {k: abs(v) for k, v in numbers.items()}
print(f"Absolute: {absolute}")

# Conditional: double positives, negate negatives
transformed = {k: v * 2 if v > 0 else -v for k, v in numbers.items()}
print(f"Transformed: {transformed}")

print("\n=== Computed Keys ===")

items = ["apple", "banana", "cherry"]

# Length as key
by_length = {len(item): item for item in items}
print(f"By length: {by_length}")

# First letter as key
by_first = {item[0]: item for item in items}
print(f"By first letter: {by_first}")
# Note: duplicates overwrite!
  1. prices ← {'apple': 1.5, 'banana': 0.75, 'cherry': 3.0}, discounted ← {'apple': 1.35, 'banana': 0.68, 'cherry': 2.7}

    3print("=== Transforming Values ===\n")45# Original prices  #?original6prices→ {'apple': 1.5, 'banana': 0.75, 'cherry': 3.0} = {"apple": 1.50, "banana": 0.75, "cherry": 3.00}7print(f"Original: {prices{'apple': 1.5, 'banana': 0.75, 'cherry': 3.0}}")89# Apply 10% discount  #?discount10discounted→ {'apple': 1.35, 'banana': 0.68, 'cherry': 2.7} = {k(empty): round(v(empty) * 0.9, 2) for k, v in prices{'apple': 1.5, 'banana': 0.75, 'cherry': 3.0}.items()}  #?transformval11print(f"10% off: {discounted{'apple': 1.35, 'banana': 0.68, 'cherry': 2.7}}")1213# Convert to cents  #?cents14cents→ {'apple': 150, 'banana': 75, 'cherry': 300} = {k(empty): int(v(empty) * 100) for k, v in prices{'apple': 1.5, 'banana': 0.75, 'cherry': 3.0}.items()}15print(f"In cents: {cents{'apple': 150, 'banana': 75, 'cherry': 300}}")1617print("\n=== Transforming Keys ===")1819# Original with lowercase keys  #?lowercase20data→ {'name': 'Alice', 'age': 30, 'city': 'NYC'} = {"name": "Alice", "age": 30, "city": "NYC"}21print(f"Original: {data{'name': 'Alice', 'age': 30, 'city': 'NYC'}}")2223# Uppercase keys  #?upperkeys24upper_keys→ {'NAME': 'Alice', 'AGE': 30, 'CITY': 'NYC'} = {k(empty).upper(): v(empty) for k, v in data{'name': 'Alice', 'age': 30, 'city': 'NYC'}.items()}  #?transformkey25print(f"Upper keys: {upper_keys{'NAME': 'Alice', 'AGE': 30, 'CITY': 'NYC'}}")2627# Add prefix to keys  #?prefix28prefixed→ {'user_name': 'Alice', 'user_age': 30, 'user_city': 'NYC'} = {f"user_{k(empty)}": v(empty) for k, v in data{'name': 'Alice', 'age': 30, 'city': 'NYC'}.items()}29print(f"Prefixed: {prefixed{'user_name': 'Alice', 'user_age': 30, 'user_city': 'NYC'}}")3031print("\n=== Transform Both ===")3233raw_scores→ {'alice': '85', 'bob': '92', 'charlie': '78'} = {"alice": "85", "bob": "92", "charlie": "78"}  #?rawscores34print(f"Raw: {raw_scores{'alice': '85', 'bob': '92', 'charlie': '78'}}")3536# Capitalize names, convert scores to int  #?both37clean_scores→ {'Alice': 85, 'Bob': 92, 'Charlie': 78} = {name(empty).capitalize(): int(score(empty)) for name, score in raw_scores{'alice': '85', 'bob': '92', 'charlie': '78'}.items()}  #?transformboth38print(f"Clean: {clean_scores{'Alice': 85, 'Bob': 92, 'Charlie': 78}}")3940print("\n=== Conditional Transform ===")4142numbers→ {'a': -3, 'b': 5, 'c': -1, 'd': 8} = {"a": -3, "b": 5, "c": -1, "d": 8}  #?numbers43print(f"Numbers: {numbers{'a': -3, 'b': 5, 'c': -1, 'd': 8}}")4445# Absolute values  #?absolute46absolute→ {'a': 3, 'b': 5, 'c': 1, 'd': 8} = {k(empty): abs(v(empty)) for k, v in numbers{'a': -3, 'b': 5, 'c': -1, 'd': 8}.items()}47print(f"Absolute: {absolute{'a': 3, 'b': 5, 'c': 1, 'd': 8}}")4849# Conditional: double positives, negate negatives  #?conditional50transformed→ {'a': 3, 'b': 10, 'c': 1, 'd': 16} = {k(empty): v(empty) * 2 if v > 0 else -v for k, v in numbers{'a': -3, 'b': 5, 'c': -1, 'd': 8}.items()}  #?condtransform51print(f"Transformed: {transformed{'a': 3, 'b': 10, 'c': 1, 'd': 16}}")5253print("\n=== Computed Keys ===")5455items→ ['apple', 'banana', 'cherry'] = ["apple", "banana", "cherry"]  #?computed5657# Length as key  #?lenkey58by_length→ {5: 'apple', 6: 'cherry'} = {len(item): item for item in items['apple', 'banana', 'cherry']}59print(f"By length: {by_length{5: 'apple', 6: 'cherry'}}")6061# First letter as key  #?firstletter62by_first→ {'a': 'apple', 'b': 'banana', 'c': 'cherry'} = {item[0](empty): item for item in items['apple', 'banana', 'cherry']}63print(f"By first letter: {by_first{'a': 'apple', 'b': 'banana', 'c': 'cherry'}}")64# Note: duplicates overwrite!
    output=== Transforming Values ===
    Original: {'apple': 1.5, 'banana': 0.75, 'cherry': 3.0}
    10% off: {'apple': 1.35, 'banana': 0.68, 'cherry': 2.7}
    In cents: {'apple': 150, 'banana': 75, 'cherry': 300}
    
    === Transforming Keys ===
    Original: {'name': 'Alice', 'age': 30, 'city': 'NYC'}
    Upper keys: {'NAME': 'Alice', 'AGE': 30, 'CITY': 'NYC'}
    Prefixed: {'user_name': 'Alice', 'user_age': 30, 'user_city': 'NYC'}
    
    === Transform Both ===
    Raw: {'alice': '85', 'bob': '92', 'charlie': '78'}
    Clean: {'Alice': 85, 'Bob': 92, 'Charlie': 78}
    
    === Conditional Transform ===
    Numbers: {'a': -3, 'b': 5, 'c': -1, 'd': 8}
    Absolute: {'a': 3, 'b': 5, 'c': 1, 'd': 8}
    Transformed: {'a': 3, 'b': 10, 'c': 1, 'd': 16}
    
    === Computed Keys ===
    By length: {5: 'apple', 6: 'cherry'}
    By first letter: {'a': 'apple', 'b': 'banana', 'c': 'cherry'}

Apply functions to keys or values: {k.upper(): v*2 for k, v in items}.

Invert a dictionary

Swap keys and values.

invert.py
Replay: real traced execution (multi-file project)
# Inverting Dictionaries

print("=== Inverting Dictionary (Swap Keys and Values) ===\n")

# Original dictionary
fruit_to_color = {"apple": "red", "banana": "yellow", "grape": "purple"}
print(f"Original: {fruit_to_color}")

# Invert: color → fruit
color_to_fruit = {v: k for k, v in fruit_to_color.items()}
print(f"Inverted: {color_to_fruit}")

print("\n=== Warning: Duplicate Values ===")

# Dict with duplicate values
grades = {"Alice": "A", "Bob": "B", "Charlie": "A", "Diana": "B"}
print(f"Grades: {grades}")

# Simple invert loses data!
grade_to_student = {v: k for k, v in grades.items()}
print(f"Inverted (data lost!): {grade_to_student}")

print("\n=== Solution: Group by Value ===")

# Collect all keys with same value
from collections import defaultdict

grade_groups = defaultdict(list)
for name, grade in grades.items():
    grade_groups[grade].append(name)
print(f"Grouped: {dict(grade_groups)}")

# Comprehension version (more complex)
unique_grades = set(grades.values())
grade_to_students = {
    grade: [name for name, g in grades.items() if g == grade]
    for grade in unique_grades
}
print(f"Comprehension: {grade_to_students}")

print("\n=== Bidirectional Lookup ===")

# Create both directions
country_code = {"USA": 1, "UK": 44, "Japan": 81}
code_country = {v: k for k, v in country_code.items()}

print(f"Country → Code: {country_code}")
print(f"Code → Country: {code_country}")

# Lookup both ways
country = "Japan"
print(f"\n{country} code: {country_code[country]}")
code = 44
print(f"Code {code}: {code_country[code]}")
  1. fruit_to_color ← {'apple': 'red', 'banana': 'yellow', 'grape': 'purple'}

    3print("=== Inverting Dictionary (Swap Keys and Values) ===\n")45# Original dictionary  #?original6fruit_to_color→ {'apple': 'red', 'banana': 'yellow', 'grape': 'purple'} = {"apple": "red", "banana": "yellow", "grape": "purple"}7print(f"Original: {fruit_to_color{'apple': 'red', 'banana': 'yellow', 'grape': 'purple'}}")89# Invert: color → fruit  #?invert10color_to_fruit→ {'red': 'apple', 'yellow': 'banana', 'purple': 'grape'} = {v(empty): k(empty) for k, v in fruit_to_color{'apple': 'red', 'banana': 'yellow', 'grape': 'purple'}.items()}  #?invertcomp11print(f"Inverted: {color_to_fruit{'red': 'apple', 'yellow': 'banana', 'purple': 'grape'}}")1213print("\n=== Warning: Duplicate Values ===")1415# Dict with duplicate values  #?duplicate16grades→ {'Alice': 'A', 'Bob': 'B', 'Charlie': 'A', 'Diana': 'B'} = {"Alice": "A", "Bob": "B", "Charlie": "A", "Diana": "B"}  #?dupevalues17print(f"Grades: {grades{'Alice': 'A', 'Bob': 'B', 'Charlie': 'A', 'Diana': 'B'}}")1819# Simple invert loses data!  #?losedata20grade_to_student→ {'A': 'Charlie', 'B': 'Diana'} = {v(empty): k(empty) for k, v in grades{'Alice': 'A', 'Bob': 'B', 'Charlie': 'A', 'Diana': 'B'}.items()}21print(f"Inverted (data lost!): {grade_to_student{'A': 'Charlie', 'B': 'Diana'}}")2223print("\n=== Solution: Group by Value ===")2425# Collect all keys with same value  #?groupby26from collections import defaultdict2728grade_groups→ defaultdict(<class 'list'>, {}) = defaultdict(list)  #?defaultdict29for name, grade in grades.items():
    output=== Inverting Dictionary (Swap Keys and Values) ===
    Original: {'apple': 'red', 'banana': 'yellow', 'grape': 'purple'}
    Inverted: {'red': 'apple', 'yellow': 'banana', 'purple': 'grape'}
    
    === Warning: Duplicate Values ===
    Grades: {'Alice': 'A', 'Bob': 'B', 'Charlie': 'A', 'Diana': 'B'}
    Inverted (data lost!): {'A': 'Charlie', 'B': 'Diana'}
    
    === Solution: Group by Value ===
  2. grade_groups[grade] ← ['Alice']

    pass 1 of 4
    28grade_groups = defaultdict(list)  #?defaultdict29for nameAlice, gradeA in grades{'Alice': 'A', 'Bob': 'B', 'Charlie': 'A', 'Diana': 'B'}.items():30    grade_groups[grade]→ ['Alice'].append(nameAlice)31print(f"Grouped: {dict(grade_groups)}")
    All 4 passes — pass 1 is the card above
    passnamegradegrade_groups[grade]
    1AliceA[] ['Alice']
    2BobB[] ['Bob']
    3CharlieA['Alice'] ['Alice', 'Charlie']
    4DianaB['Bob'] ['Bob', 'Diana']
  3. unique_grades ← {'A', 'B'}, grade_to_students ← {'A': ['Alice', 'Charlie'], 'B': ['Bob', 'Diana']}

    30    grade_groups[grade].append(name)31print(f"Grouped: {dict(grade_groupsdefaultdict(<class 'list'>, {'A': ['Alice', 'Charlie'], 'B': ['Bob', 'Diana']}))}")3233# Comprehension version (more complex)  #?groupcomp34unique_grades→ {'A', 'B'} = set(grades{'Alice': 'A', 'Bob': 'B', 'Charlie': 'A', 'Diana': 'B'}.values())35grade_to_students→ {'A': ['Alice', 'Charlie'], 'B': ['Bob', 'Diana']} = {36    grade: [nameDiana for name, g(empty) in grades{'Alice': 'A', 'Bob': 'B', 'Charlie': 'A', 'Diana': 'B'}.items() if g == grade]37    for grade in unique_grades{'A', 'B'}38}  #?nestedcomp39print(f"Comprehension: {grade_to_students{'A': ['Alice', 'Charlie'], 'B': ['Bob', 'Diana']}}")4041print("\n=== Bidirectional Lookup ===")4243# Create both directions  #?bidirectional44country_code→ {'USA': 1, 'UK': 44, 'Japan': 81} = {"USA": 1, "UK": 44, "Japan": 81}45code_country→ {1: 'USA', 44: 'UK', 81: 'Japan'} = {v(empty): k(empty) for k, v in country_code{'USA': 1, 'UK': 44, 'Japan': 81}.items()}  #?codemap4647print(f"Country → Code: {country_code{'USA': 1, 'UK': 44, 'Japan': 81}}")48print(f"Code → Country: {code_country{1: 'USA', 44: 'UK', 81: 'Japan'}}")4950# Lookup both ways51country→ Japan = "Japan"52print(f"\n{countryJapan} code: {country_code[country]81}")53code→ 44 = 4454print(f"Code {code44}: {code_country[code]UK}")55#@help original
    outputGrouped: {'A': ['Alice', 'Charlie'], 'B': ['Bob', 'Diana']}
    Comprehension: {'A': ['Alice', 'Charlie'], 'B': ['Bob', 'Diana']}
    
    === Bidirectional Lookup ===
    Country → Code: {'USA': 1, 'UK': 44, 'Japan': 81}
    Code → Country: {1: 'USA', 44: 'UK', 81: 'Japan'}
    
    Japan code: 81
    Code 44: UK

{v: k for k, v in d.items()} swaps keys and values.

dict inversion Swap keys and values: `{v: k for k, v in d.items()}`. Only works with unique values.

Exercise: practical.py

Real-world dictionary comprehension patterns