Python Dictionaries and Sets

Learn how Python dictionaries store values under keys, so you can look data up by name, count how often things occur, group items into categories and organize records inside other records. Then use sets to remove duplicates and compare collections with union, intersection and difference, and learn when a dictionary, set, list or tuple is the right choice.

BeginnerLesson 7 of 10 in Python for Beginners: Introduction to Programming

What you will learn

  1. Explain what a dictionary is, build one from key-value pairs, read values by key without crashing on missing keys, and add, change and remove entries.
    • Build dictionaries from key-value pairs
      Describe a dictionary as a collection that maps unique keys to values, write dictionary literals, build dictionaries with dict(), and pick keys that Python accepts.
    • Look up values by key safely
      Read a value with square brackets, check whether a key exists with in, and use get() to supply a default value instead of stopping on a missing key.
    • Add, change and remove entries
      Insert new items, update existing values, merge two dictionaries, and delete entries with del, pop() and related methods.
  2. Visit every key, value or item of a dictionary, compute totals and sorted reports, and create new dictionaries with loops and dictionary comprehensions.
    • Loop over keys, values and items
      Use for loops with a dictionary, .values() and .items(), sort keys by name or by value, and avoid changing a dictionary's size while looping over it.
    • Build new dictionaries from existing data
      Create dictionaries with loops and dictionary comprehensions to transform values, filter items, pair up lists and swap keys with values.
  3. Use a dictionary as a set of counters, collect items into groups, and add up totals per category, the everyday jobs dictionaries do in real programs.
    • Count how often things occur
      Build a frequency table with a dictionary of counters, count words in a piece of text, find the most common items, and recognize Counter as a shortcut.
    • Group items and total values by category
      Collect items into lists under a shared key, add up amounts per category, compute group averages, and avoid lists that are accidentally shared between keys.
  4. Represent records as dictionaries inside dictionaries or lists, read and update values at any depth, and loop through nested data to summarize it.
    • Store and access records in nested dictionaries
      Build dictionaries of dictionaries, lists of dictionaries and dictionaries of lists, reach values with chained lookups, update them, and copy nested data safely.
    • Loop through and summarize nested data
      Use loops, including nested loops, to report on, filter and summarize records, and handle records with missing fields or empty lists.
  5. Create sets of unique values, test membership, compare collections with union, intersection and difference, and choose between lists, tuples, dictionaries and sets.
    • Create sets and remove duplicates
      Write and change sets, explain why they hold no duplicates and no order, test membership, and remove duplicates from a list with or without keeping its order.
    • Compare collections with set operations
      Use union, intersection, difference and symmetric difference, test subsets, supersets and disjoint sets, and tell operators that return new sets from methods that change a set.
    • Choose the right collection for a task
      Compare lists, tuples, dictionaries and sets, pick the one a task needs, and combine them, including set operations on dictionary keys.

Python Dictionaries study guide

5 chapters

1

Store and look up data with dictionaries

A dictionary connects each key to a value, making named lookup useful for contacts, inventory, and other records. Building and changing one starts with knowing what a key identifies and what its value means. Safe lookup then lets a program distinguish a missing record from an existing value of zero. Adding, merging, and removing pairs changes that stored information while following predictable rules for insertion order.

1.1 Build dictionaries from key-value pairs

A dictionary stores pairs: a key identifies an item, and its value holds the information you want. A contact list is a useful model: a name leads to a phone number. A dictionary lookup uses a key, even when that key happens to be a number.

Write the pairs
ages = {"Ana": 31, "Ben": 27, "Cara": 35}
print(ages["Ben"])
print(len(ages))

This prints 27 and then 3. The colon joins each key to its value; commas separate the pairs. len counts pairs. Both {} and dict() create an empty dictionary.

Each key appears only once. In {"a": 1, "b": 2, "a": 3}, the later value for "a" replaces the earlier one, leaving {'a': 3, 'b': 2}. Two different keys may have the same value: {"Ana": "blue", "Ben": "blue"} still has two items.

Build from other data

Choose the form that matches the input:

colors = dict(red=1, blue=2)
coordinates = dict([("x", 10), ("y", 20)])
labels = dict(zip(["a", "b", "c"], [1, 2, 3]))

The first form makes string keys from the argument names. The second reads a sequence of two-item pairs. The third pairs corresponding elements of two lists, producing {'a': 1, 'b': 2, 'c': 3}. The strings in the first form are 'red' and 'blue', not variable lookups.

Pick usable keys

Dictionary keys must be hashable. Strings and numbers work, as do tuples made entirely of hashable items. Lists, dictionaries, and ordinary sets do not work as keys. For a location, use (2, 3), a tuple, instead of [2, 3], a list:

board = {(0, 0): "start", (2, 3): "treasure"}
print(board[(2, 3)])

This prints treasure. The parentheses make the coordinate pair one key. A tuple containing a list still fails the hashability rule. Dictionary values have no such restriction: a value can be a list, another dictionary, or any other type.

Equal numeric keys refer to the same entry. Because 1, 1.0, and True compare equal, {1: "one", 1.0: "float one"} holds one pair, with the value 'float one'. The string "1" is a separate key from the number 1.

Keep order and identity separate

Since Python 3.7, dictionaries preserve insertion order. The ages above appear as Ana, Ben, Cara when printed or looped over. They still have keys, not list positions: ages[0] asks for the key 0 and raises KeyError: 0.

Dictionaries are mutable. After backup = ages, both names refer to the same dictionary. Setting backup["Ana"] = 32 also changes the value reached through ages. To copy the outer dictionary, write backup = ages.copy() or backup = dict(ages). Separate outer dictionaries can still share nested lists and dictionaries.

Key Takeaways

  • Each unique key maps to one value; len(d) counts the pairs.
  • Keys must be hashable; values can be any type.
  • Equal keys share one entry, and later assignments replace its value.
  • Insertion order does not turn dictionary keys into positions.
  • Assignment shares a dictionary; copy() creates a separate outer dictionary.

1.2 Look up values by key safely

A lookup should match what a missing key means in your program. Sometimes it signals a mistake. Sometimes it is normal, such as a product that has not been counted yet. Python gives you separate ways to handle those cases.

Read an existing value
stock = {"apples": 12, "pears": 0, "plums": 7}
print(stock["plums"])

The square-bracket lookup returns 7. Keys match exactly: "Plums" is different from "plums". Reading stock["kiwis"] raises KeyError: 'kiwis', because that key is absent. It does not supply an empty value or a count of zero.

Use this direct lookup when a key is required. An error then draws attention to incomplete data or a spelling mistake at the place it occurs.

Test for a key

The expression key in stock tests whether a key exists. "pears" in stock is True, although its stored value is zero. "kiwis" not in stock is also True.

item = "kiwis"
if item in stock:
    print(stock[item])
else:
    print("No stock record for", item)

Here the missing key leads to a message. The lookup happens only in the branch where the key exists.

Membership on a dictionary searches keys. 12 in stock is False; to ask whether any item has a stored value of 12, write 12 in stock.values(). The collection you put after in determines what is searched.

Read with a default

stock.get("kiwis") returns None without raising KeyError. Supply a second argument to choose a different default: stock.get("kiwis", 0) returns 0. Neither call inserts a new item. After both calls, the dictionary still contains only apples, pears, and plums.

Question the program asksUseful form
What is the value for this required key?stock[item]
Does this key exist?item in stock
What is the value, or a fallback if absent?stock.get(item, 0)

The default replaces a missing lookup, not a stored value. stock.get("pears", 99) returns 0, because pears already has a value.

Do not confuse zero with missing

if stock.get("pears"): checks the truth of the returned value. Zero is false, so that branch is skipped. The same test also skips a missing key whose lookup returns None. To distinguish those cases, test key membership directly.

Process a whole order
prices = {"coffee": 3.5, "tea": 2.75}
order = ["tea", "coffee", "tea", "soda"]
total = 0
for item in order:
    if item in prices:
        total += prices[item]
    else:
        print("No price for", item)
print(total)

The first tea brings the total to 2.75, coffee brings it to 6.25, and the second tea brings it to 9.0. Soda produces the message No price for soda and adds nothing. A direct lookup on every pass would fail on soda; silently using a default price of zero would hide the missing price. The separate branch makes that missing information visible.

Key Takeaways

  • d[key] raises KeyError when the key is missing.
  • in tests keys, including keys whose values are zero or empty.
  • get returns a value or a default without inserting a key.
  • Choose a default only when it makes sense for the task.

1.3 Add, change and remove entries

Dictionary updates use keys to identify what changes. Assigning a value can add a new pair or replace an old value. Removing a pair can also return information you need, such as the quantity removed from an inventory.

Add and replace
scores = {"Ana": 8}
scores["Ben"] = 6
scores["Ana"] = 9
scores["Ben"] += 2
print(scores)

The result is {'Ana': 9, 'Ben': 8}. Ben is added, Ana is updated, and then Ben's existing score increases. The += line first reads the old value, so it raises KeyError for a missing key. Dictionaries have no append method.

Combine dictionaries

update copies pairs into an existing dictionary. With those scores, scores.update({"Ben": 7, "Cara": 10}) changes Ben to 7 and adds Cara with 10.

Since Python 3.9, the merge operator can build a new dictionary:

left = {"x": 1, "y": 2}
right = {"y": 5, "z": 3}
merged = left | right
print(merged)

This prints {'x': 1, 'y': 5, 'z': 3}. The right side wins for a shared key. left stays unchanged; left |= right would update it in place.

update() returns None. Writing scores = scores.update(new_scores) changes the old dictionary and then makes scores refer to None. Call update on its own line. Assign the result of left | right when you want a new merged dictionary.

Remove pairs
OperationEffect and return value
del d[key]Removes the pair; a missing key raises KeyError.
d.pop(key)Removes the pair and returns its value; a missing key raises KeyError.
d.pop(key, 0)Returns 0 if the key is absent.
d.popitem()Removes and returns the most recently inserted pair as a tuple.
d.clear()Removes all pairs and returns None.

For {"a": 1, "b": 2, "c": 3}, popitem() returns ('c', 3). This uses insertion order, not alphabetical order or the largest value.

Follow an inventory change
inventory = {"pens": 10, "pads": 4}
inventory["pens"] -= 3
inventory["clips"] = 50
removed = inventory.pop("pads")

The sale leaves 7 pens. Adding clips creates a new key. Removing pads stores 4 in removed, leaving {'pens': 7, 'clips': 50}. The return from pop lets the program use the removed quantity after the pair is gone.

Insert only when absent

setdefault(key, default) returns the existing value, or inserts and returns the default when the key is missing. For stock = {"apples": 12, "pears": 0, "plums": 7}, stock.setdefault("kiwis", 0) inserts kiwis and returns 0. stock.setdefault("apples", 99) returns 12 and leaves apples unchanged. This insertion is the difference from get.

Updating an existing key leaves its place unchanged. Starting with {"a": 1, "b": 2, "c": 3}, setting d["a"] = 10 keeps "a" first. Deleting "a" and inserting it again puts it after "c". A replacement value and a newly inserted pair affect order differently.

Key Takeaways

  • d[key] = value adds a key or replaces its value.
  • For dictionary merges, the right-hand value wins a shared key.
  • pop returns a removed value; popitem returns the last inserted pair.
  • update and clear return None.
  • setdefault inserts a default only for an absent key.
  • Updating preserves a key's place; deleting and reinserting moves it to the end.
2

Loop through dictionaries and build new ones

Loops turn a dictionary into a report, a total, or the input to a new collection. The first choice is what each pass needs: a key, a value, or both parts of a pair. Sorting controls a report's order without rearranging the original dictionary. A comprehension can express a short rule for keeping or transforming pairs, while ordinary loops leave room for several processing steps and checks.

2.1 Loop over keys, values and items

Choose a loop that gives you the part of each pair you need. A dictionary alone supplies keys. Its views can supply values or whole pairs, so you do not have to recover information that the loop could hand you directly.

Visit keys, values, or pairs
temps = {"Mon": 68, "Tue": 75, "Wed": 71}
for day, temp in temps.items():
    print(day, temp)

The temperatures are in degrees Fahrenheit. This prints Mon 68, Tue 75, and Wed 71 on separate lines, in insertion order. Each item is a two-element tuple that the loop unpacks into day and temp.

Loop inputWhat each pass receives
temps or temps.keys()A day key
temps.values()A temperature value
temps.items()A (day, temperature) pair

With for day in temps:, use temps[day] inside the loop when you need the matching value. If the program needs both parts each time, .items() usually states the job more clearly.

Understand views

keys(), values(), and items() return views, which reflect later changes to their dictionary. They are not lists and have no positional indexing. temps.keys()[0] raises TypeError. Convert to a list when you need a snapshot with positions: list(temps) gives ['Mon', 'Tue', 'Wed'].

Compute a total or find a matching key

sum(temps.values()) returns 214, and dividing by len(temps) gives an average of about 71.33. max(temps.values()) returns 75. To find which day has that value, write max(temps, key=temps.get), which returns 'Tue'.

The key= argument supplies a function used for comparison. Here Python visits day keys and calls temps.get for each one to obtain its temperature. Write the function name without calling it: temps.get, not temps.get(). If values tie, max returns the first key it encounters.

Sort a report

sorted(temps) returns keys in alphabetical order. sorted(temps.items()) returns pairs sorted by key. To sort day keys by temperature, use sorted(temps, key=temps.get), producing ['Mon', 'Wed', 'Tue']. Add reverse=True for ['Tue', 'Wed', 'Mon']. These calls return lists; they do not rearrange temps.

grades = {"Ana": 88, "Ben": 72, "Cara": 95}
passing = 0
for name, grade in grades.items():
    print(f"{name}: {grade}")
    if grade >= 75:
        passing += 1

The report prints each name with its grade. Ana and Cara meet the threshold, so passing ends at 2.

Remove entries without disrupting the scan

Do not add or delete keys while iterating directly over a dictionary. Changing its size can raise RuntimeError: dictionary changed size during iteration. Replacing an existing value is allowed.

To remove cooler days, use for day in list(temps): and delete temps[day] when its value is below 70. The loop walks a separate list of keys, leaving {'Tue': 75, 'Wed': 71} in the dictionary. Building a new filtered dictionary is another way to keep the scan separate from the changes.

Key Takeaways

  • Loop over a dictionary for keys, .values() for values, or .items() for pairs.
  • Views reflect changes; lists provide positional access.
  • key=d.get compares stored values while returning or sorting keys.
  • Sorting returns a list and leaves dictionary order unchanged.
  • Scan a copied key list when deleting entries.

2.2 Build new dictionaries from existing data

A new dictionary often comes from a rule applied to existing data. Start with a loop you can explain, then use a comprehension when the same rule fits clearly into one expression.

Build one pair at a time
words = ["kiwi", "fig", "banana"]
lengths = {}
for word in words:
    lengths[word] = len(word)

Each pass chooses a word as the key and its length as the value. The result is {'kiwi': 4, 'fig': 3, 'banana': 6}. The dictionary is created before the loop so that earlier pairs remain available on later passes.

A dictionary comprehension expresses the same work:

lengths = {word: len(word) for word in words}

Read the for part to see what is visited, then the expression before it to see what pair is produced. The colon separates the key expression from the value expression. Without that colon, {word for word in words} builds a set.

Keep some items

An if clause filters the input:

grades = {"Ana": 88, "Ben": 72, "Cara": 95}
high_grades = {
    name: grade
    for name, grade in grades.items()
    if grade >= 80
}

Ana and Cara pass the test, giving {'Ana': 88, 'Cara': 95}. Ben's pair is left out. The input dictionary is unchanged; the result holds only pairs that meet the condition.

Transform values

A comprehension can keep the days while converting Fahrenheit readings to Celsius:

temps = {"Mon": 68, "Tue": 75, "Wed": 71}
celsius = {
    day: round((f - 32) * 5 / 9, 1)
    for day, f in temps.items()
}

The result is {'Mon': 20.0, 'Tue': 23.9, 'Wed': 21.7}. For Tuesday, subtracting 32 gives 43; multiplying by 5 and dividing by 9 gives about 23.89. round(..., 1) stores 23.9. The key stays the same while the value changes.

Pair lists carefully

dict(zip(names, scores)) pairs each name with the score at the same position. zip stops when the shorter input ends. Pairing ["Ana", "Ben", "Cara"] with [90, 85] gives {'Ana': 90, 'Ben': 85}. No error reports Cara's missing score, so check the input lengths when every name must have one.

Swap keys and values
favorites = {"Ana": "blue", "Ben": "red", "Cara": "blue"}
by_color = {color: name for name, color in favorites.items()}

The result is {'blue': 'Cara', 'red': 'Ben'}. Both Ana and Cara would need the same new key, so Cara's later pair replaces Ana's. Inversion preserves all pairs only when the old values are unique and hashable. A list value cannot become a dictionary key at all. To keep several names under one color, store a list of names under that color.

Use an ordinary loop when the job needs several statements, messages, or checks. A comprehension is useful because it makes a short rule visible; squeezing a larger procedure into it makes the rule harder to follow.

Key Takeaways

  • A dictionary comprehension produces a key-value pair for each selected input.
  • An if clause filters; the pair expressions can transform the data.
  • zip stops at the shorter input.
  • Inverting a dictionary can lose entries when values repeat.
3

Count and group data with dictionaries

Dictionaries can collect results while a loop processes data. A counter stores one number per distinct item; a grouping dictionary stores several members under each category. Both patterns must handle the first appearance of a key and preserve what earlier passes accumulated. Once the groups exist, their lists support totals and averages, and standard-library helpers can shorten the initialization work.

3.1 Count how often things occur

A frequency table answers how often each distinct item occurs. Its keys identify the items; its values are counters. The dictionary grows when a new item appears, while later appearances increase an existing count.

Trace a counter
counts = {}
for letter in "banana":
    if letter in counts:
        counts[letter] += 1
    else:
        counts[letter] = 1

The first letter creates 'b': 1. The next creates 'a': 1, and then 'n': 1. The next "a" raises its existing count to 2. After the last two letters, the dictionary is {'b': 1, 'a': 3, 'n': 2}. Its order records when each letter first appeared, not which letter is most common.

Use zero before the first occurrence

The two branches can become one assignment:

counts = {}
for letter in "banana":
    counts[letter] = counts.get(letter, 0) + 1

The right side reads the previous count, using zero when the key is missing, then adds one. The left side stores that new count. get itself does not insert anything; the assignment does.

Using only counts[letter] += 1 fails when a letter is new. Moving counts = {} inside the loop causes a different problem: each pass erases the earlier counts. Initialize once before processing the items.

Decide what counts as the same word

For text, case and punctuation affect the keys. The strings "The" and "the" differ, as do "dog." and "dog". Clean the forms before using them as keys:

text = "The cat saw the dog. The dog ran."
counts = {}
for word in text.lower().split():
    word = word.strip(".,!?")
    counts[word] = counts.get(word, 0) + 1

This produces {'the': 3, 'cat': 1, 'saw': 1, 'dog': 2, 'ran': 1}. lower handles case, split separates words at whitespace, and strip removes the listed punctuation characters from the ends. It does not remove punctuation from the middle of a word.

Find the most common items

For this nonempty table, max(counts, key=counts.get) returns 'the'. To find the two most common words, use sorted(counts, key=counts.get, reverse=True)[:2], giving ['the', 'dog']. Equal counts keep their original order when sorted.

The pattern also counts numbers or tuples. For rolls [3, 6, 3, 1, 6, 3], it builds {3: 3, 6: 2, 1: 1}. A value never observed has no entry. Read it with a default of zero when that is useful.

Recognize the library shortcut
from collections import Counter
letter_counts = Counter("banana")
print(letter_counts.most_common(1))
print(letter_counts["z"])

This prints [('a', 3)] and then 0. The import makes Counter available from Python's standard library. A Counter is a dictionary designed for counts: its keys are hashable items, and direct lookup of a missing item returns zero. Its displayed counts for this input are Counter({'a': 3, 'n': 2, 'b': 1}).

Key Takeaways

  • A frequency table maps each distinct item to its count.
  • Initialize the dictionary before the loop.
  • counts[item] = counts.get(item, 0) + 1 handles new and repeated items.
  • Clean words before counting when case and punctuation should be ignored.
  • Compare counts with key=counts.get to rank items.
  • Counter builds counts and returns zero for missing-key lookups.

3.2 Group items and total values by category

A dictionary can store a whole group under each key. The key names the category, and a list holds the items assigned to it. This keeps every member available for later totals, averages, or reports.

Build separate lists for groups
words = ["apple", "bean", "avocado", "beet", "corn"]
groups = {}
for word in words:
    first = word[0]
    if first not in groups:
        groups[first] = []
    groups[first].append(word)

For "apple", the program creates an empty list under "a" and appends the word. "bean" starts a separate "b" list. "avocado" joins the existing "a" list. The result is {'a': ['apple', 'avocado'], 'b': ['bean', 'beet'], 'c': ['corn']}.

The empty list is created only for a new label. Creating it on every pass would discard the earlier members of that group.

Shorten the initialization

groups.setdefault(word[0], []).append(word) performs the same grouping step. setdefault returns the existing list if there is one. Otherwise it stores the supplied empty list and returns it. The following append changes that returned list.

Another option creates lists automatically:

from collections import defaultdict
groups = defaultdict(list)
for word in words:
    groups[word[0]].append(word)

Pass list, the function that creates a fresh list, without parentheses. On a missing-key lookup, this defaultdict creates and stores a new empty list. Even a read such as groups["z"] inserts that missing key. Use "z" in groups when you only want to check whether a group exists.

Keep the lists independent

groups = dict.fromkeys(["a", "b"], []) places the same list under both keys. Appending 1 through groups["a"] then gives {'a': [1], 'b': [1]}. The lists are shared, not copied.

To start with separate lists, use {key: [] for key in keys}, setdefault with a fresh [], or defaultdict(list). Each new category must receive its own list object.

Add amounts per category

Counting adds one per occurrence. A category total adds each item's amount:

expenses = [("food", 12.5), ("travel", 30),
            ("food", 7.25), ("books", 18)]
totals = {}
for category, amount in expenses:
    totals[category] = totals.get(category, 0) + amount

Food starts at 12.5 and then gains 7.25, ending at 19.75. Travel totals 30 and books total 18. Storing amount alone would replace the previous total instead of adding to it.

Average or deduplicate a group

For scores = {"A": [80, 90], "B": [70]}, loop over scores.items() and calculate sum(values) / len(values). Group A averages 85.0; group B averages 70.0. Test if values: before dividing so an empty group is handled separately.

When repeats should disappear within each group, use sets as values. tags.setdefault(post, set()).add(tag) creates a set for a new post and adds its tag. A repeated tag remains one element; a list would keep each occurrence.

Key Takeaways

  • Grouping maps a category to its members, often in a list.
  • Create a fresh list for each group.
  • setdefault and defaultdict(list) simplify group initialization.
  • Category totals add amounts; averages divide each group's sum by its own count.
  • Use sets as group values when repeated members should disappear.
4

Model structured data with nested dictionaries

Related fields belong together in a record, and several records can be organized by ID or kept as rows in a list. Accessing the right value means moving through each level in order. Reports then combine an outer record loop with field lookups or an inner loop over a stored list. Missing optional fields, empty lists, and shared inner objects each affect how those records should be read, summarized, or copied.

4.1 Store and access records in nested dictionaries

A record brings related fields together, such as a student's age, major, and grades. A nested dictionary stores another dictionary as a value. The outer keys can identify records, while the inner keys identify fields.

Read one level at a time
students = {
    "ana": {"age": 19, "major": "math", "grades": [88, 92]},
    "ben": {"age": 22, "major": "history", "grades": [75, 81, 79]},
}

students["ana"] gives Ana's record dictionary. Adding ["major"] reads its major, so students["ana"]["major"] returns 'math'. For Ben's latest grade, students["ben"]["grades"][-1] reaches the record, then its list, then the last list element, 79.

Each lookup acts on the object returned by the previous lookup. The same square-bracket syntax can mean a dictionary key at one level and a list position at another.

Change a field or add a record
students["ana"]["age"] = 20
students["ben"]["email"] = "ben@example.com"
students["cara"] = {"age": 21, "major": "art", "grades": []}
students["cara"]["grades"].append(90)

The first two lines change or add fields inside existing records. The third adds a whole record under a new ID. The fourth reaches Cara's grades list and appends a score to it.

Assigning students["dev"]["age"] = 30 fails because the outer lookup for "dev" happens first and raises KeyError: 'dev'. Create the record before assigning its fields.

For an optional read, students.get("dev", {}).get("age") returns None. The first default is an empty dictionary, so the second get has a dictionary to read even when the record is absent. For these records, each outer value is itself a dictionary.

Choose a shape that fits access

A list of dictionaries keeps rows in order:

rows = [{"name": "Ana", "city": "Austin"},
        {"name": "Ben", "city": "Denver"}]
print(rows[1]["city"])

This prints Denver: list index first, field key second. A dictionary of lists, such as {"A": [80, 90], "B": [70]}, stores several values per label. These structures can be combined when a record needs both named fields and an ordered list.

When names uniquely identify rows, build by_name = {row["name"]: row for row in rows}. Then by_name["Ben"] finds Ben's row directly. The values are the existing row dictionaries, so edits through this index also affect those rows. If names repeat, a later row replaces an earlier one under that key.

Copy nested data deliberately

backup = students shares the entire dictionary. backup = students.copy() makes a separate outer dictionary but keeps the same inner records. After that shallow copy, backup["ana"]["age"] = 99 also changes Ana's age in students.

import copy
independent = copy.deepcopy(students)
independent["ana"]["age"] = 25

For these nested dictionaries and lists, the deep copy makes separate inner objects as well. Changing the copied age leaves the original age alone. Use consistent field names across records so the same lookup code works for each record.

Key Takeaways

  • Chained lookups move through one collection at a time.
  • Create an inner dictionary before assigning a field inside it.
  • A list of records uses an index first; a dictionary of records uses an ID.
  • A shallow copy shares inner records; a deep copy separates nested mutable data.

4.2 Loop through and summarize nested data

Processing nested data means keeping track of which level the loop has reached. An outer loop chooses a record. A field lookup reaches a value inside that record, and an inner loop can then visit the elements of a stored list.

Summarize one record per pass
students = {
    "ana": {"major": "math", "grades": [88, 92]},
    "ben": {"major": "history", "grades": [75, 81, 79]},
    "cara": {"major": "art", "grades": []},
}
for name, info in students.items():
    grades = info["grades"]
    major = info["major"]
    if grades:
        average = sum(grades) / len(grades)
        print(f"{name}: {major}, average {average:.1f}")
    else:
        print(f"{name}: {major}, no grades")

Ana's scores total 180, so her average is 90.0. Ben's total is 235 over three scores, giving about 78.33; the format :.1f displays 78.3. Cara's list is empty, so the program prints cara: art, no grades without dividing by zero.

Assigning grades and major inside the loop gives each name the current record's values. The average also belongs inside the loop: it must be calculated separately for each student.

Read optional fields

info.get("email", "no email") supplies text for an optional email field. A direct info["email"] would raise KeyError for a record without it. A default belongs at the level where the field may be missing. The outer dictionary's get would search student IDs, not email fields.

Select records
math_students = []
for name, info in students.items():
    if info["major"] == "math":
        math_students.append(name)

This produces ['ana']. The condition reads a field of the current record; the appended value is the outer key. If the report needed whole records, it could append info instead. Decide which kind of result the next part of the program needs.

Visit every stored score
count = 0
for info in students.values():
    for grade in info["grades"]:
        if grade > 80:
            count += 1

The inner loop visits Ana's 88 and 92, then Ben's 75, 81, and 79. Cara's empty list adds no passes. Three scores exceed 80: 88, 92, and 81. The count is initialized outside both loops because it describes all students together. Resetting it inside the outer loop would keep only the last record's count.

Count records by a field
majors = {}
for info in students.values():
    major = info["major"]
    majors[major] = majors.get(major, 0) + 1

Each record contributes one to its major. For Ana and Ben alone, the result is {'math': 1, 'history': 1}; including Cara adds 'art': 1. To total or group a different field, keep the outer record loop and change the value it contributes.

For readable reports, print one formatted line per record instead of the whole nested dictionary. In an f-string, store a field in a variable first, as above, or use the opposite quote style inside the braces, as in f"{name}: {info['major']}".

Key Takeaways

  • An outer loop chooses a record; field lookups work inside it.
  • Guard an empty list before dividing by its length.
  • Use get on the record for an optional field.
  • An inner loop visits each element in a record's list.
  • Put an accumulator outside the loops whose results it combines.
5

Use sets to remove duplicates and compare collections

Sets focus on which values are present. Removing duplicates and comparing membership become direct operations, from finding shared course enrollments to checking missing skills. Order and repeated occurrences call for other collections, so the choice matters before data is converted. Sets also connect back to dictionaries: their keys can be compared as sets even when the stored values differ.

5.1 Create sets and remove duplicates

A set records which distinct values are present. It keeps each element once and has no guaranteed order. Sets suit membership checks and removing duplicates when the number of occurrences is unimportant.

Create a set
colors = {"red", "green"}
numbers = set([3, 1, 3, 2, 1])
print(len(numbers))
print(sorted(numbers))

This prints 3 and then [1, 2, 3]. Repeated inputs become a single element. An empty set is set(); {} makes an empty dictionary.

set("banana") visits the string's characters, leaving the distinct letters "a", "b", and "n". {"banana"} supplies the whole string as one element. As with dictionary keys, equal numeric values count once: {1, 1.0, True} has one element.

Elements must be hashable. Numbers, strings, and tuples of hashable values work; lists, dictionaries, and ordinary sets do not. Use (1, 2) for a coordinate element instead of [1, 2]. A frozenset is an immutable set and can itself be a set element or dictionary key.

Work without positions

colors[0] raises TypeError because a set has no positions. Its printed order is not guaranteed, and string elements may print in a different order on another run. sorted(colors) produces a new sorted list when the elements can be compared. It does not give the set an order.

Change the members
OperationWhat happens
s.add(x)Adds one element; a duplicate has no effect.
s.update(items)Adds elements from an iterable.
s.remove(x)Removes x; an absent element raises KeyError.
s.discard(x)Removes x if present; absence is allowed.
s.pop()Removes and returns an arbitrary element.
s.clear()Removes every element.

add("blue") adds one string. update(["blue", "gold"]) adds two strings. Using update("blue") instead adds separate characters, because a string is iterable. Sets have no append method.

Preserve first appearances when needed

list(set(items)) removes duplicates but loses their original order. If first appearances matter, use dictionary insertion order:

items = [3, 1, 3, 2, 1]
unique = list(dict.fromkeys(items))
print(unique)

This prints [3, 1, 2]. The values become dictionary keys, so each appears once in the order first encountered.

You can also keep the roles explicit:

seen = set()
unique = []
for item in items:
    if item not in seen:
        seen.add(item)
        unique.append(item)

The set answers whether an item has appeared; the list keeps first appearances in order. Both forms require hashable input items.

Count distinct items or check membership

For the eight words in "the cat saw the dog the dog ran".split(), len(set(words)) is 5: the, cat, saw, dog, and ran. This counts different words, not their frequencies.

A blocked-sender set lets sender in blocked answer whether an address is present. For large collections, set and dictionary membership is typically much faster than searching a list one item at a time.

Key Takeaways

  • A set stores unique hashable elements without a guaranteed order.
  • Use set() for an empty set; {} is a dictionary.
  • remove raises on absence; discard allows it.
  • sorted(s) returns a list; set elements have no positions.
  • list(dict.fromkeys(items)) removes repeats while keeping first appearances.
  • len(set(items)) counts distinct values.

5.2 Compare collections with set operations

Set operations express questions about membership in two collections. Use the operation that matches the question: anyone in either collection, only shared members, or members left after exclusions.

Read the four operations

Suppose the course enrollments are:

python = {"Ana", "Ben", "Cara", "Dev"}
sql = {"Ben", "Dev", "Eli"}
ExpressionMembership ruleMembers, listed alphabetically
`pythonsql`In either set or both
python & sqlIn both setsBen, Dev
python - sqlIn Python but not SQLAna, Cara
python ^ sqlIn exactly one setAna, Cara, Eli

Union includes all five students once. Intersection keeps only the two shared students. Difference starts from the left set and excludes anything in the right set. Reversing the difference changes the question: sql - python contains only Eli. Symmetric difference keeps the two nonoverlapping parts; it equals union minus intersection.

The named forms are python.union(sql), python.intersection(sql), python.difference(sql), and python.symmetric_difference(sql).

Test a relationship

a <= b asks whether every member of a belongs to b. That is the subset test. a < b also requires b to have at least one extra member, making a a proper subset. a >= b and a > b test the corresponding superset relationships.

print({"Ben"} <= sql)
print(sql <= sql)
print(sql < sql)
print(python.isdisjoint(sql))

These print True, True, False, and False. A set is a subset of itself but not a proper subset of itself. Disjoint sets have no shared member; Python and SQL share Ben and Dev. The method forms issubset and issuperset also return Boolean results.

Keep results separate or change a set

result = a | b creates a new set, leaving both inputs unchanged. The in-place forms a |= b, a &= b, a -= b, and a ^= b change a to the union, intersection, difference, or symmetric difference. Any other name referring to that same set sees the change.

Named set methods accept iterables such as lists. python.union(["Fay"]) works. The ordinary set operators require set operands: {"a"} | ["b"] raises TypeError.

Use | to combine sets, not +. Also keep & separate from and: {1, 2} and {3} returns {3} because the left set is truthy. It does not calculate common members.

Find missing requirements
required = {"python", "sql", "git"}
skills = {"python", "excel", "git"}
missing = required - skills
extra = skills - required
qualified = required <= skills

The missing set contains "sql"; the extra set contains "excel". The intersection contains "git" and "python". qualified is False, because at least one required skill is absent. A candidate may have many skills and still fail the subset test: the particular required members must all be present.

Key Takeaways

  • | takes either set, & takes both, and ^ takes exactly one.
  • a - b keeps only members of a that are absent from b.
  • <= allows equal sets; < requires a proper subset.
  • isdisjoint tests whether there are no shared members.
  • Ordinary set operators create results; in-place forms change the left set.

5.3 Choose the right collection for a task

Choose a collection by the job the program must do with it. Order, repeats, named lookup, and changeability are separate needs. A program may use several collection types because different parts of its data serve different jobs.

Compare the built-in collections
TypeHow you reach dataOrder and repeatsCan the collection change?
ListBy positionOrdered; repeats allowedYes
TupleBy positionOrdered; repeats allowedNo
DictionaryBy keyInsertion order; unique keysYes
SetBy membershipNo guaranteed order; unique elementsYes

A list suits a sequence of events: the order matters, and the same event can occur more than once. A tuple suits a fixed group of related values, such as coordinates. A tuple can hold a mutable object, so the tuple's fixed slots do not make every contained object immutable. Only a tuple of hashable items can be a dictionary key or set element.

A dictionary suits named information: an ID leads to a record or a product name leads to a quantity. Its values can repeat and can be whole collections. A set suits a membership question: the program needs to know whether an ID is present, not a separate value for it.

Preserve the information the task needs

Converting [1, 2, 1] to a set loses both the repeated occurrence and the sequence. That is useful for a distinct-item list, but wrong for a complete event log. A dictionary such as {"reader": True, "editor": True} can often become {"reader", "editor"} when the values carry no additional information. If each role needs a permission level, keep the dictionary.

Equality follows each collection's meaning. [1, 2] == [2, 1] is False, because sequence order differs. {1, 2} == {2, 1} is True. Dictionaries with equal key-value pairs compare equal even if the keys were inserted in different orders. Their insertion order affects iteration, not that equality test.

Compare dictionary keys as sets
store_a = {"pens": 10, "pads": 4, "ink": 2}
store_b = {"pads": 7, "clips": 30, "ink": 5}
common = store_a.keys() & store_b.keys()
only_a = store_a.keys() - store_b.keys()

The common keys are "ink" and "pads"; only_a contains "pens". These are products carried, regardless of their quantities. The two stores have different amounts of ink, but ink is still a shared key.

Dictionary key views support set operations because keys are unique and hashable. Value views do not support these operators: store_a.values() & {1} raises TypeError. Converting values to a set is possible when they are hashable, but discards repeated values and asks a different question from comparing product keys.

Combine shapes in one program

A library can use a dictionary from book IDs to record dictionaries, a set of currently borrowed IDs, and a list of today's checkouts in time order. A tuple such as ("Dune", 1965) holds a title and year together. The dictionary finds a book's details; the set checks borrowing status; the list preserves the day's history.

Key Takeaways

  • Use dictionaries for lookup by a name or ID and sets for distinct membership.
  • Use lists for ordered, changeable sequences and tuples for fixed groups.
  • List equality depends on order; dictionary and set equality do not.
  • Key-view set operations compare keys, not the values stored under them.

Python Dictionaries examples

5 Walkthroughs

1

Build and maintain a stock dictionary

14 steps
Create key-value pairs, choose safe lookups, and trace inventory changes and merges.
  1. 1
    IntroductionFind information by a name

    An inventory needs to connect a product name to its quantity. A dictionary stores that relationship as a key-value pair: the name is the key, and the quantity is the value.

    You will build a small inventory, decide what a missing product means, and trace changes to existing and new products. Keep track of two things separately: whether a key exists and what value it stores.

  2. 2
    ExampleWrite the first inventory
    stock = {"pens": 10, "pads": 4}
    

    Each colon joins a key to its value, and the comma separates the pairs. stock["pens"] reads 10; len(stock) is 2, the number of pairs.

    The key identifies the product. stock[0] would search for the key 0, not the first product. Although dictionaries preserve insertion order, their entries are still reached by keys.

  3. 3
    ExplanationChoose keys Python can store

    Keys must be hashable. Strings and numbers work, as do tuples containing only hashable items. A location such as (2, 3) can be one key, while the list [2, 3] cannot.

    Values can be any type, including lists or dictionaries. This rule applies to the key, so storing a list as a value does not stop the pair from being valid.

  4. 4
    ChallengeCount the stored pairs

    What is the length of {"pens": 10, "pads": 4, "pens": 7}, and what value is stored for "pens"?

    ---reveal---

    The length is 2, and pens has value 7. The later pair replaces the earlier value under the same key. It does not create a second pens entry. Different keys may share a value, but one key cannot hold two separate pairs.

  5. 5
    ExplanationDecide what absence means

    stock["clips"] raises KeyError because the current inventory has no clips key. Use direct lookup when a record is required and a missing record needs attention.

    stock.get("clips", 0) instead returns the fallback zero without adding clips. That suits a calculation where an absent product should count as no stored stock. The dictionary still has two entries after this call.

  6. 6
    Key InsightA stored zero still has a key

    Suppose stock["pads"] = 0 records that pads are sold out. "pads" in stock is still True, because the record exists.

    if stock.get("pads"): skips the branch because zero is false. That test cannot distinguish sold out from a missing record returning None. When the question is whether a record exists, test the key with in.

  7. 7
    ChallengeKeep sold-out products visible

    Starting with stock = {"pens": 10, "pads": 0}, a report should show the quantity for pads and print "missing" for an absent product. What test should decide whether to read stock[item]?

    ---reveal---

    Use if item in stock:. Pads passes that test and displays zero. In the else branch, print "missing". A truth test of the returned quantity would wrongly treat the sold-out record as absent.

  8. 8
    ExampleApply a sale and a delivery

    Start a fresh inventory:

    stock = {"pens": 10, "pads": 4}
    stock["pens"] -= 3
    stock["clips"] = 50
    

    The sale reads the old pen quantity and stores 7. The delivery creates a new clips key with value 50. The -= line requires pens to exist already; plain assignment can create a missing key. A dictionary has no append method.

  9. 9
    ExampleRecover a removed quantity

    Continue the inventory:

    removed = stock.pop("pads")
    

    removed becomes 4, and the dictionary becomes {"pens": 7, "clips": 50}. pop both changes the collection and returns the removed value.

    Use del stock["pads"] when you only need removal. Both forms raise KeyError on absence unless pop receives a default, such as stock.pop("pads", 0).

  10. 10
    ChallengeHandle a second removal

    The current inventory is {"pens": 7, "clips": 50}. What does stock.pop("pads", 0) return, and what happens to the inventory?

    ---reveal---

    It returns 0 and leaves the inventory unchanged, because pads is already absent. The default prevents a missing-key error; it does not create a pads pair. An existing key would be removed and its stored value returned instead.

  11. 11
    ExplanationMerge settings without losing the base

    For two dictionaries, base | overrides creates a new result and lets the right side win shared keys:

    base = {"size": 2, "color": "blue"}
    result = base | {"size": 5}
    

    result has size 5 and color "blue"; base still has size 2. This operator is available since Python 3.9. base.update(overrides) would change the base instead and return None.

  12. 12
    TipFollow order through changes

    Replacing a value keeps its key in place. Deleting a key and adding it again puts it at the end. popitem() removes the most recently inserted pair, not the largest value.

    Also distinguish method return values: update() and clear() return None, while pop() returns a value. Do not assign an update result back to the name you need for the dictionary.

  13. 13
    ChallengeUse a default without overwriting

    A program starts with stock = {"pens": 7}. It calls stock.get("clips", 20), then stock.setdefault("clips", 5), then adds 2 to stock["clips"]. What is the final clips quantity?

    ---reveal---

    It is 7. get returns 20 but inserts nothing. setdefault then creates clips with 5, and the final update adds 2. A lookup default is not a stored value unless an operation actually inserts it.

  14. 14
    RecapTrack the key and the value

    Build a dictionary from key-value pairs, then choose lookup behavior deliberately: direct access for required records, in for existence, and get for a fallback.

    Assignments add or replace. Removal methods may return useful data, and merging may either create a new dictionary or change an existing one. When tracing code, record each insertion, value replacement, and deletion in order.

2

Turn dictionary data into reports

12 steps
Choose loop inputs, sort by keys or values, and build filtered or transformed dictionaries.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionChoose what each loop receives
  2. 2
    ExampleReceive both parts of a pair
  3. 3
    Key InsightA view stays connected
  4. 4
    ExampleSort by a stored value
  5. 5
    ChallengeKeep names in value order
  6. 6
    ExampleBuild a dictionary with a loop
  7. 7
    ConnectionExpress the same rule compactly
  8. 8
    ExampleFilter first, then produce the pair
  9. 9
    ChallengeCombine a filter and a transformation
  10. 10
    TipCheck the pairs before constructing
  11. 11
    ChallengeRemove low entries without disrupting the loop
  12. 12
    RecapMatch the input to the result
3

Build counts, groups, and category totals

13 steps
Trace first occurrences, preserve group members, and calculate results for each category.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionLet each category collect a result
  2. 2
    ExampleGive a new item its first count
  3. 3
    ExampleUse zero for an unseen item
  4. 4
    ChallengeFind why a count never grows
  5. 5
    TipClean before choosing the key
  6. 6
    ExplanationKeep the members of each group
  7. 7
    ExampleTrace a list-valued update
  8. 8
    Key InsightEvery group needs a separate list
  9. 9
    ChallengePredict an automatic new group
  10. 10
    ExampleAdd amounts instead of occurrences
  11. 11
    ExampleAverage the values in each group
  12. 12
    ChallengeChoose what each record contributes
  13. 13
    RecapPreserve the result between passes
4

Read and summarize nested records

11 steps
Follow chained lookups, copy records deliberately, and report across stored lists.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionSeparate record IDs from fields
  2. 2
    ExampleFollow the path to a score
  3. 3
    ChallengeAdd a field to a new record
  4. 4
    Key InsightCopying the outside can share the inside
  5. 5
    ChallengeKeep experimental grades independent
  6. 6
    ExampleCalculate one average per record
  7. 7
    TipHandle a record with no grades
  8. 8
    ConnectionRead fields at the record level
  9. 9
    ExampleVisit all grades across the records
  10. 10
    ChallengeCombine a field and a stored list
  11. 11
    RecapKeep each level visible
5

Compare membership and choose collections

15 steps
Remove repeats, use set operations, and combine sets with records and ordered sequences.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionAsk who belongs to each collection
  2. 2
    ExplanationBuild unique membership
  3. 3
    TipAdd and remove the intended element
  4. 4
    ExamplePreserve first appearances
  5. 5
    ChallengeKeep the original sequence of distinct labels
  6. 6
    ExampleFind everyone or only shared students
  7. 7
    ExampleRead difference from left to right
  8. 8
    ChallengeFind people in exactly one club
  9. 9
    ExplanationCheck every requirement
  10. 10
    Key InsightDistinguish a result from a changed set
  11. 11
    ConnectionKeep history, identity, and membership
  12. 12
    ExampleCompare keys without comparing quantities
  13. 13
    ChallengeChoose a collection for a growing log
  14. 14
    ChallengeCombine key views with a missing-record check
  15. 15
    RecapChoose the membership question first

Python Dictionaries practice questions

40 Practice Questions in 4 sets

Set 1: Read and change Python collections10 Practice Questions

Question 1 of 10

How many items are in {"oak": 4, "pine": 7, "oak": 9}?
  1. 3
  2. 2
  3. 4
  4. 6
Show answerHide answer
Answer: B
The repeated key "oak" keeps its last value, 9, so the dictionary has the two keys "oak" and "pine". Counting all three written pairs misses the replacement: a dictionary cannot hold two separate entries under the same key. The number of items is the number of distinct keys.

Question 2 of 10

For levels = {"east": 0, "west": 5}, what does "east" in levels return?
  1. False
  2. 0
  3. None
  4. True
Show answerHide answer
Answer: D
Membership checks whether "east" is a key, and it is present with a stored value of zero. A zero value makes a truth test of the value false, but it does not remove the key. The result of in is a Boolean, not the value stored under the key.

Question 3 of 10

What does this code print?

seats = {"front": 6, "back": 8}
removed = seats.pop("front")
seats["back"] -= 2
print(removed, seats["back"])
  1. 6 6
  2. 6 8
  3. None 6
  4. 0 6
Show answerHide answer
Answer: A
pop("front") removes the pair and returns its value, so removed becomes 6. The remaining back-seat count falls from 8 to 6. Treating pop as a method that returns None confuses it with methods such as clear, which change a collection without returning an item.

Question 4 of 10

What does sum({"small": 3, "large": 9}.values()) return?
  1. 2
  2. 9
  3. 12
  4. 6
Show answerHide answer
Answer: C
The values view supplies the numbers 3 and 9, and sum adds them to give 12. The two key-value pairs do not make the sum 2; that would be the dictionary's length. Calling .values() selects the quantities that the calculation needs.

Question 5 of 10

What dictionary does {name: len(name) for name in ["elm", "cedar"]} create?
  1. {3: 'elm', 5: 'cedar'}
  2. {'elm': 5, 'cedar': 3}
  3. {'elm': 3, 'cedar': 5}
  4. {'elm': 1, 'cedar': 1}
Show answerHide answer
Answer: C
The expression before the colon supplies each key, so the names remain keys. len(name) supplies the corresponding value: 3 for "elm" and 5 for "cedar". Reversing the pairs would require the length expression before the colon and the name expression after it.

Question 6 of 10

What is the value of counts["up"] after this loop?

counts = {}
for move in ["up", "left", "up", "up"]:
    counts[move] = counts.get(move, 0) + 1
  1. 3
  2. 1
  3. 2
  4. 4
Show answerHide answer
Answer: A
The first "up" stores 1, the second increases it to 2, and the third increases it to 3. The "left" entry has its own counter and does not increase "up". Counting all four loop passes would give the total number of moves, not the frequency of this particular move.

Question 7 of 10

What is groups["r"] after this code?

groups = {}
for word in ["rose", "mint", "reed"]:
    groups.setdefault(word[0], []).append(word)
  1. ['reed']
  2. ['rose', 'mint', 'reed']
  3. ['r', 'r']
  4. ['rose', 'reed']
Show answerHide answer
Answer: D
The first word creates the "r" list and appends "rose"; "reed" later joins that same list. The "m" group holds "mint" separately. setdefault preserves an existing list, so it does not replace the existing list with a new empty list on the last pass.

Question 8 of 10

For devices = {"d7": {"ports": [2, 4, 8]}}, what does devices["d7"]["ports"][-1] return?
  1. 2
  2. 8
  3. 4
  4. 3
Show answerHide answer
Answer: B
The first lookup selects the device record, the second selects its ports list, and [-1] selects the last list element, 8. A dictionary key and a list index perform different jobs within the chain. The list length is 3, but the expression asks for an element, not its length.

Question 9 of 10

What does len(set([8, 2, 8, 5, 2])) return?
  1. 2
  2. 4
  3. 3
  4. 5
Show answerHide answer
Answer: C
The set contains the three distinct numbers 8, 2, and 5. Repeated appearances do not create new elements, so the length is 3. The input list has five positions, but converting it to a set discards the extra occurrences before len is evaluated.

Question 10 of 10

A service requires {"read", "write"}. An account has {"read", "share"}, and a new grant adds {"write"}. Which expression tests whether the account meets every requirement after the grant?
  1. required <= (current | grant)
  2. required <= (current & grant)
  3. required >= (current | grant)
  4. required < (current & grant)
Show answerHide answer
Answer: A
Union adds the grant to the current permissions, producing read, share, and write. The subset test then checks that every required permission belongs to that combined set. Intersection would keep only permissions already present in both inputs, which are disjoint here, so it would discard the new grant instead of adding it.
Set 2: Trace lookups, groups, and records10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

After rates = {"basic": 7} and result = rates.get("plus", 0), what are result and len(rates)?
  1. 0 and 2
  2. None and 1
  3. 0 and 1
  4. 7 and 1
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

What does this code print?

settings = {"sound": 2, "light": 4}
settings.update({"sound": 5})
del settings["sound"]
settings["sound"] = 1
print(list(settings))
  1. ['light', 'sound']
  2. ['sound', 'light']
  3. ['light']
  4. ['sound', 'light', 'sound']
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

For wait = {"A": 9, "B": 3, "C": 6}, what does sorted(wait, key=wait.get) return?
  1. ['A', 'B', 'C']
  2. ['B', 'C', 'A']
  3. ['A', 'C', 'B']
  4. [3, 6, 9]
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

What does this code print?

from collections import Counter
counts = Counter([4, 4, 7])
print(counts[9])
  1. None
  2. 1
  3. KeyError: 9
  4. 0
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

What does this code print?

groups = dict.fromkeys(["indoor", "outdoor"], [])
groups["indoor"].append(12)
groups["outdoor"].append(18)
print(groups["indoor"])
  1. [12]
  2. [18]
  3. [[12], [18]]
  4. [12, 18]
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

What does this code print?

original = {"r1": {"visits": 2}}
backup = original.copy()
backup["r1"]["visits"] += 3
backup["r2"] = {"visits": 1}
print(original["r1"]["visits"], "r2" in original)
  1. 2 False
  2. 5 False
  3. 5 True
  4. 2 True
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A record has {"scores": []}. What condition should guard sum(scores) / len(scores) after scores = record["scores"]?
  1. if scores:
  2. if "scores" in record:
  3. if scores is not None:
  4. if len(scores) >= 0:
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

What method call removes "paused" from states while allowing it to be absent?
  1. states.remove("paused")
  2. states.pop("paused")
  3. states.discard("paused")
  4. states.clear("paused")
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

For morning = {"Ivo", "June", "Kai"} and evening = {"June", "Mina"}, what are the members of morning ^ evening?
  1. Ivo, June, Kai, Mina
  2. Ivo, Kai, Mina
  3. June
  4. Ivo, Kai
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A monitor must keep every sensor reading in arrival order, including repeats, and separately check whether each sensor ID is authorized. What pair of collections best fits?
  1. A list of readings and a set of authorized IDs.
  2. A set of readings and a list of authorized IDs.
  3. A dictionary keyed by reading and a set of authorized IDs.
  4. A tuple of readings and a dictionary keyed by reading.
Show answerHide answer

Save this lesson to see this answer.

Set 3: Debug collection transformations10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

What is len({1: "first", True: "second", "1": "third"})?
  1. 1
  2. 3
  3. 6
  4. 2
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A stock report must print a stored quantity, including zero, or "missing" when the product key is absent. Which function body meets that requirement?
  1. if stock.get(product):
        return stock[product]
    return "missing"
    
  2. if product in stock:
        return stock[product]
    return "missing"
    
  3. return stock.get(product) or "missing"
    
  4. if product in stock.values():
        return stock[product]
    return "missing"
    
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

What dictionary remains after this inversion?

team = {"Luz": "design", "Omar": "support", "Pia": "design"}
by_role = {role: name for name, role in team.items()}
  1. {'design': 'Pia', 'support': 'Omar'}
  2. {'design': ['Luz', 'Pia'], 'support': ['Omar']}
  3. {'design': 'Luz', 'support': 'Omar'}
  4. {'Luz': 'design', 'Omar': 'support', 'Pia': 'design'}
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

After counting words from "Go go! Stop." using lower().split() and word.strip(".,!?"), what is the count for "go"?
  1. 2
  2. 1
  3. 3
  4. 0
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

A totals loop processes [("repair", 14), ("delivery", 6), ("repair", 9)]. With totals[category] = totals.get(category, 0) + amount, what is totals["repair"]?
  1. 9
  2. 14
  3. 23
  4. 29
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A dictionary contains records as dictionary values. What does records.get("x9", {}).get("email", "none") return when "x9" is absent?
  1. {}
  2. None
  3. KeyError: 'x9'
  4. "none"
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

What does this code print?

records = {"a": {"scores": [6, 9]}, "b": {"scores": [8]},
           "c": {"scores": []}}
count = 0
for info in records.values():
    for score in info["scores"]:
        if score >= 8:
            count += 1
print(count)
  1. 0
  2. 1
  3. 2
  4. 3
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

What does list(dict.fromkeys(["z", "m", "z", "a"])) return?
  1. ['a', 'm', 'z']
  2. ['z', 'm', 'a']
  3. ['z', 'm', 'z', 'a']
  4. ['m', 'z', 'a']
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

What does {2, 5} < {2, 5} return?
  1. True
  2. False
  3. set()
  4. None
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

What does this code print?

first = {"lamp": 4, "cord": 9, "plug": 2}
second = {"cord": 3, "plug": 8, "case": 5}
result = {name: first[name]
          for name in first.keys() & second.keys()
          if first[name] < second[name]}
print(sorted(result.items()))
  1. [('cord', 9)]
  2. [('plug', 8)]
  3. [('cord', 9), ('plug', 2)]
  4. [('plug', 2)]
Show answerHide answer

Save this lesson to see this answer.

Set 4: Combine collection skills10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A grid stores values by coordinate pairs. What key can Python accept directly?
  1. [3, 5]
  2. (3, 5)
  3. {3, 5}
  4. {"x": 3, "y": 5}
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

What does this code print?

stock = {"bolts": 0}
first = stock.get("nuts", 4)
second = stock.setdefault("nuts", 6)
print(first, second, len(stock))
  1. 4 4 2
  2. 4 6 1
  3. 4 6 2
  4. 6 6 2
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

What does this code print?

base = {"size": 2, "mode": 1}
alias = base
merged = base | {"size": 5}
alias["mode"] = 3
print(merged["size"], merged["mode"], base["size"])
  1. 5 3 5
  2. 5 3 2
  3. 2 1 2
  4. 5 1 2
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

What does this code print?

levels = {"low": 2, "high": 8, "mid": 5}
view = levels.keys()
for name in list(levels):
    if levels[name] < 5:
        del levels[name]
print(list(view))
  1. ['low', 'high', 'mid']
  2. ['high', 'mid']
  3. ['mid', 'high']
  4. ['low']
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

What does this code produce?

names = ["Rae", "Sol", "Tia"]
scores = [7, 9]
result = {name: score * 2 for name, score in zip(names, scores)
          if score >= 8}
  1. {'Sol': 18}
  2. {'Rae': 14, 'Sol': 18}
  3. {'Sol': 9}
  4. {'Sol': 18, 'Tia': 18}
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

What does this code print?

from collections import defaultdict
groups = defaultdict(list)
groups["red"].append(5)
unused = groups["blue"]
print(len(groups), len(unused))
  1. 1 0
  2. 2 1
  3. 1 1
  4. 2 0
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

What overall average does this data give when every score has equal weight?

records = {"p": {"scores": [10, 20]},
           "q": {"scores": [90]}, "r": {"scores": []}}
  1. 40.0
  2. 52.5
  3. 60.0
  4. 30.0
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

What does this code print?

records = {"v1": {"team": "north", "scores": [2, 6]},
           "v2": {"team": "south", "scores": []},
           "v3": {"team": "north", "scores": [4]}}
totals = {}
for info in records.values():
    team = info["team"]
    for score in info["scores"]:
        totals[team] = totals.get(team, 0) + score
print(totals.get("south", 0), totals["north"])
  1. 0 4
  2. 1 12
  3. 0 12
  4. 0 8
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

What does this code print?

required = {"a", "b", "c"}
current = {"a", "d"}
missing = required - current
current |= {"b"}
print(sorted(missing), sorted(required - current))
  1. ['c'] ['c']
  2. ['b', 'c'] ['b', 'c']
  3. ['b', 'c'] ['c']
  4. ['d'] ['c']
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

What does this code print?

left = {"x": 2, "y": 4}
right = {"y": 4, "x": 2}
print(left == right, list(left) == list(right))
  1. True False
  2. True True
  3. False True
  4. False False
Show answerHide answer

Save this lesson to see this answer.

Stuck on your own question? Homework Help

Key Terms

62 Key Terms, each with its definition

A

Accumulator
An accumulator is a variable that collects a result across loop passes, such as a running total or a count of qualifying entries.
An accumulator initialized before the grades loop can count all students who reach the passing score.

C

Category total
A category total is the sum of amounts assigned to one label, built by adding each new amount to that label's previous total.
A category total for food adds all food expenses, even when travel expenses occur between them.
Chained lookup
A chained lookup applies several accesses in sequence, each to the object returned by the previous dictionary or list access.
The chained lookup devices["d7"]["ports"][0] reaches a record, its ports list, then the first port.
Collection equality
Collection equality compares contents according to the collection type: lists require matching order, while dictionaries and sets ignore order.
Collection equality makes {"a": 1, "b": 2} equal to the same pairs inserted in the opposite order.
Comparison key
A comparison key is the value produced by the function passed as key=, used to compare items while keeping the original items as results.
With sorted(wait, key=wait.get), each stored wait time is the comparison key for its station name.
Counter
A Counter is a standard-library dictionary type for counting hashable items, with zero returned for a missing-item lookup.
A Counter built from "level" records two occurrences of "l", two of "e", and one of "v".

D

Deduplication
Deduplication removes repeated occurrences, leaving one representative of each distinct value, with order preserved only by an appropriate method.
Deduplication with list(dict.fromkeys(items)) keeps hashable items in their first-appearance order.
Deep copy
A deep copy recursively copies nested collections, making separate dictionaries and lists that can be edited independently of the original.
A deep copy lets a program try new scores in a copied record without editing the original scores list.
Default factory
A default factory is the function a defaultdict calls without arguments to create a value for a missing-key lookup.
The default factory list creates a fresh empty list for each new key in defaultdict(list).
Default value
A default value is a fallback supplied for a missing lookup, such as the second argument of a dictionary's get method.
In stock.get("soap", 0), the default value is zero; the call does not create a soap entry.
Defaultdict
A defaultdict is a dictionary type that creates and stores a value from a supplied factory when a missing key is read with square brackets.
A defaultdict made with list starts a separate empty list whenever a new group key is first read.
Dictionary
A dictionary is a mutable collection that maps unique, hashable keys to values and preserves the order in which keys were inserted.
A dictionary can map each product name to its current quantity, such as {"tape": 8, "glue": 3}.
Dictionary comprehension
A dictionary comprehension builds a new dictionary by producing key-value pairs from an iterable, optionally filtering the inputs.
The dictionary comprehension {word: len(word) for word in words} stores a length under each word.
Dictionary view
A dictionary view is a dynamic object returned by keys(), values(), or items() that reflects changes to the dictionary.
A saved dictionary view from stock.keys() shows a new product after that product is added.
Difference
The difference a - b contains members of the left set that are absent from the right set, so the order of the operands matters.
The difference required - skills finds requirements the candidate lacks, not the candidate's extra skills.
Discard
The set method discard removes a specified element when present and leaves the set unchanged when the element is absent.
Calling discard with blocked.discard(address) allows an already-unblocked address without an error.
Disjoint sets
Disjoint sets share no element, so their intersection is empty and calling a.isdisjoint(b) returns True.
The sets of odd and even rolls on a die are disjoint sets because no possible roll belongs to both.
Distinct count
A distinct count measures how many different values occur, found with len(set(items)) when the input items are hashable.
The distinct count of [7, 7, 2, 7] is two, while its total number of occurrences is four.

E

Element
An element is one member of a set; equal values count as the same member even when they were supplied more than once.
The element 3 appears once in set([3, 3, 5]), so the resulting set has only two members.
Empty-list guard
An empty-list guard checks that a list contains values before an operation that needs them, such as dividing a sum by the list's length.
The empty-list guard if scores: keeps a record with no scores from causing division by zero.

F

Filter
A filter keeps only inputs that meet a condition; a comprehension's final if clause decides which inputs produce pairs.
A filter such as if quantity > 0 leaves out products with zero stock when building a new dictionary.
Formatted report
A formatted report presents selected data in readable output, such as one line per record with an average shown to one decimal place.
A formatted report can use f"{name}: {average:.1f}" to display an ID and its rounded average.
Frequency table
A frequency table maps each distinct item to its number of occurrences, often using a dictionary with integer counts as values.
A frequency table for rolls [2, 5, 2] stores a count of two under 2 and one under 5.
Frozenset
A frozenset is an immutable set whose hashability lets it serve as a dictionary key or as an element of another set.
A frozenset can represent a fixed group of tags when that whole group must be used as a dictionary key.

G

Grouping
Grouping collects inputs under shared category labels, often mapping each label to a list of all members assigned to it.
Grouping filenames by their first letter puts "map" and "memo" in the same "m" list.

H

Hashable
An object is hashable when it can serve as a dictionary key or set element; strings, numbers, and tuples of hashable items qualify.
The tuple (4, 7) is hashable and can identify a grid location, while the list [4, 7] cannot.

I

Initialization
Initialization gives a variable its starting value before processing, such as an empty dictionary before a counting loop.
Initialization of counts = {} inside the loop would erase the counts collected on earlier passes.
Insertion order
Insertion order is the order in which dictionary keys were added, preserved when iterating or displaying the dictionary.
In insertion order, "west" stays before "east" if it was added first, even if its value changes.
Intersection
The intersection of two sets contains only the elements present in both, excluding members found in just one input.
The intersection of enrolled IDs and paid IDs identifies the people who belong to both groups.
Inversion
Dictionary inversion swaps keys with values; it needs hashable values, and repeated values collapse into a single new key.
Inversion of two names with the same favorite color preserves only the last name under that color.
Items
The items view supplies dictionary entries as key-value tuples, so a loop can receive both parts of each stored pair.
The items view in for city, temp in temps.items(): gives each city together with its temperature.
Iteration
Iteration visits the elements supplied by a collection, one per loop pass; iterating directly over a dictionary supplies its keys.
Iteration over {"west": 4, "east": 9} visits "west" and then "east", not the stored quantities.

K

Key
A key identifies one value in a dictionary; using the key retrieves that value without relying on the pair's position.
The key "glue" retrieves the quantity 3 from a dictionary that stores quantities by product name.
Key-value pair
A key-value pair is one dictionary item, made of a unique key and its associated value; a colon joins them in a literal.
The key-value pair "room": 12 associates the field name "room" with the number 12.
Key-view intersection
A key-view intersection applies & to dictionary key views, returning the keys present in both dictionaries without comparing their values.
A key-view intersection of two stores' stock dictionaries finds products both stores carry, even when their stock quantities differ.
KeyError
A KeyError is an exception raised by a missing dictionary-key lookup, or by certain removal operations on absent keys or elements.
The expression stock["soap"] raises KeyError if no soap entry exists in the stock dictionary.

L

List
A list is a mutable, ordered sequence that allows repeated values and supports access to elements by their positions.
A list of checkouts preserves the same book ID twice when the book is checked out twice in one day.
Lookup
A dictionary lookup uses a key to retrieve its associated value; square-bracket lookup raises an error when that key is absent.
The lookup prices["juice"] retrieves the stored price, provided the dictionary has a "juice" key.

M

Membership test
A membership test uses in or not in to ask whether a collection contains an item; on a dictionary, it checks keys.
The membership test "soap" in stock stays true when the stored soap quantity is zero.
Merge
A dictionary merge combines pairs into one result; with a | b, shared keys take their values from b and both inputs stay unchanged.
The merge defaults | overrides lets an override replace a default value for the same setting.
Mutation
A mutation changes an existing object, such as adding a dictionary pair or replacing its value, without creating a replacement object.
The assignment stock["soap"] = 6 is a mutation visible through any other name for that dictionary.

N

Nested dictionary
A nested dictionary holds another dictionary as a value, allowing outer keys to identify records and inner keys to identify fields.
A nested dictionary of students lets students["ana"]["major"] read one field of Ana's record.
Nested loop
A nested loop runs an inner loop during each pass of an outer loop, such as visiting every score inside every record.
A nested loop over students and their grades can count qualifying grades across the entire class.

O

Optional field
An optional field may be absent from some records, so reading it with get can supply a fallback without raising KeyError.
An optional field for email can be shown as "no email" when a student record does not contain it.

P

Pop
The dictionary method pop removes a specified key and returns its stored value, using a supplied default if the key is absent.
A call to inventory.pop("pads") uses pop to recover the old quantity while removing that product.
Popitem
The dictionary method popitem removes and returns the most recently inserted key-value pair as a two-element tuple.
After adding keys "a" then "b", popitem() returns the pair for "b", even if its value is smaller.
Proper subset
A proper subset is a subset that is not equal to the containing set, which must have at least one additional element.
The proper subset test {2} < {2, 4} is true, while {2} < {2} is false because the sets are equal.

R

Record
A record stores related fields about one entity, often as a dictionary whose keys name fields such as age, major, or scores.
A record for one device can hold its model as a string and its available ports as a list.

S

Set
A set is a mutable collection of unique, hashable elements with no guaranteed order, used for membership and collection comparisons.
A set of borrowed book IDs answers whether an ID is present without storing a separate value for it.
Setdefault
The dictionary method setdefault returns an existing value, or first inserts and returns a default when its key is missing.
Grouping with setdefault creates a list for a new category and preserves the list for an existing one.
Shallow copy
A shallow copy creates a separate outer collection while reusing references to the original collection's inner objects.
A shallow copy of student records still shares each student dictionary, so changing an age affects both.
Shared mutable value
A shared mutable value is one changeable object stored or named in several places, so an edit through one reference appears through the others.
A shared mutable value results when dict.fromkeys(keys, []) places one list under every group key.
Subset
A subset has every one of its elements contained in another set; the <= test allows the two sets to be equal.
The subset test required <= skills succeeds only when the candidate has every required skill.
Superset
A superset contains every element of another set; a >= b tests whether a contains all members of b, allowing equality.
The superset test skills >= required checks whether the candidate has all required skills.
Symmetric difference
The symmetric difference contains elements in exactly one of two sets, removing shared members from their combined membership.
The symmetric difference of two club rosters contains people who joined one club but not both.

T

Text normalization
Text normalization makes chosen differences consistent before processing, such as lowercasing words so case does not split their counts.
Text normalization can make "Map" and "map" share one word-count key by lowercasing both.
Tuple
A tuple is an ordered collection with fixed slots; its items cannot be replaced, though a contained mutable object may still change.
A tuple such as ("Dune", 1965) keeps a title and its publication year together as one pair.
Tuple unpacking
Tuple unpacking assigns the elements of a tuple to separate names, such as the key and value received from a dictionary item.
Tuple unpacking in for name, score in scores.items(): makes both parts available in the loop body.

U

Union
The union of two sets contains every element found in either set or both, with each equal element appearing once.
The union morning | evening lists everyone attending either session, including people attending both.
Update
An update copies pairs into an existing dictionary, adding new keys and replacing values under keys that already exist.
Calling stock.update({"soap": 6}) performs an update and returns None, not the updated dictionary.

V

Value
A dictionary value is the object stored under a key, and it can be a number, string, list, dictionary, or any other type.
The value under "scores" can be a list, allowing one record to hold all of a learner's scores.

Z

Zip
The function zip pairs corresponding elements from its inputs and stops when the shortest input has no more elements.
Using zip to pair names and scores omits unmatched names when the scores list is shorter.

About this lesson

By StudeliReport a mistake

Make your own Study Materials

Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.

Get Started