Model keyed records, required and optional fields, counters, merges, uniqueness, and group relationships.
Mappings and sets organize data by identity rather than position. A dictionary maps each unique key to a value, making named lookup explicit. A set stores unique values and makes membership, deduplication, and comparisons between groups concise. Both rely on hashable keys or members for fast average-case lookup.
Learning goals
Create dictionaries and choose meaningful, hashable keys.
Distinguish required lookup with brackets from optional lookup with get.
Add, update, remove, iterate, copy, and merge mappings deliberately.
Use dictionary comprehensions and counting patterns without hiding missing-data rules.
Create sets for uniqueness and efficient membership.
Apply union, intersection, difference, and symmetric difference to real problems.
Map unique keys to values
A dictionary stores key-value associations. Each key appears at most once and identifies its value; assigning the same key again replaces that value. Modern Python dictionaries preserve insertion order, but lookup is based on the key, not a numeric position.
Keys should represent stable identity. Strings, numbers, tuples of hashable values, and frozen sets can be keys. Lists, dictionaries, and ordinary sets are mutable and therefore unhashable. Values have no such restriction and can contain any Python object.
Separate required and optional keys
Brackets express a required field: record[key] returns its value or raises KeyError when the key is absent. get expresses an optional field: it returns None or a supplied default when the key is missing. Choose between them based on the data contract, not merely to avoid an exception.
PYTHON · EDITABLE
profile ={"name":"Amina","completed_lessons":4,}
name = profile["name"]
city = profile.get("city")
theme = profile.get("theme","system")print(name, city, theme)
Test dictionary membership by key
The expression key in mapping checks keys, not values. This distinction matters when a stored value may be None: get cannot tell whether the key is absent or present with None unless you use a unique sentinel. Membership followed by bracket lookup makes that state explicit.
PYTHON · EDITABLE
settings ={"theme":None}
missing =object()
value = settings.get("theme", missing)if value is missing:print("Theme key is absent")else:print("Theme key is present with:", value)print("theme"in settings)print(Nonein settings.values())
Update and remove entries deliberately
Assignment adds or replaces one entry. update applies entries from another mapping or iterable of pairs. setdefault returns an existing value or inserts a default when absent. pop removes a key and returns its value; del removes a required key; popitem removes the most recently inserted pair.
PYTHON · EDITABLE
counts:dict[str,int]={}for language in["python","html","python","css"]:
counts[language]= counts.get(language,0)+1
counts.update({"javascript":2})
python_count = counts.pop("python")print(python_count)print(counts)
Use setdefault carefully with mutable values. It is concise for grouping, but collections.defaultdict can state a repeated factory more clearly. Never use the same pre-created mutable object as the default for several keys unless sharing is intentional.
Iterate through keys, values, and pairs
Iterating over a dictionary yields keys. keys(), values(), and items() return dynamic view objects connected to the dictionary. Use items when both key and value matter. Do not structurally change a dictionary while iterating over its live view; iterate over a list copy when removal is required.
A dictionary comprehension produces one key-value pair for each source item, optionally filtering items. Keys must remain unique; if the same key is produced more than once, the later value wins. Use an explicit loop when collision handling or validation needs several steps.
PYTHON · EDITABLE
raw_scores ={"amina":84,"youssef":-1,"salma":93}
valid_scores ={
name.title(): score
for name, score in raw_scores.items()if0<= score <=100}print(valid_scores)
Merge and copy dictionaries
The | operator creates a new merged dictionary, while |= and update mutate the dictionary on the left. When keys overlap, values from the right side win. copy and dict(source) create shallow copies, so nested mutable values remain shared just as they do with lists.
A set is an unordered collection of unique hashable values. Repeated inputs collapse to one member. Use set() for an empty set because {} creates an empty dictionary. Do not depend on a set's display or iteration order; sort its values when output must be deterministic.
PYTHON · EDITABLE
languages =["python","html","python","css"]
unique_languages =set(languages)
unique_languages.add("javascript")
unique_languages.discard("sql")print(sorted(unique_languages))print(len(unique_languages))
add inserts one member. remove raises KeyError when the member is absent, while discard does nothing. pop removes an arbitrary member rather than the oldest or newest one. clear removes every member.
Compare groups with set operations
Union combines all members. Intersection keeps members shared by both sets. Difference keeps members from the left that are absent from the right. Symmetric difference keeps members present in exactly one set. Operator direction matters for difference.
A set is a subset when all its members occur in another set; <= tests subset and < tests proper subset. Superset operators reverse the relationship. isdisjoint reports whether two sets share no members. These operations often express permission, feature, and validation rules more directly than nested loops.
Use frozenset when the set itself must be hashable
frozenset is an immutable set. It supports non-mutating set operations and can be used as a dictionary key or member of another set. Use it when a group of unique values acts as stable identity, not merely to prevent accidental edits.
Dictionary key lookup and set membership are constant-time on average. List membership may inspect every item. Hash tables use additional memory and require hashable identity, so they are not automatically better than lists. Choose based on whether the problem is about ordered positions, named keys, or unique membership.
Use a dictionary for records, indexes, caches, counters, and named lookup.
Use a set for uniqueness, repeated membership tests, and group comparison.
Use a list when order and duplicates are central.
Sort dictionary keys or set members only when presentation requires deterministic order.
Measure real workloads before optimizing a collection choice.
Common mapping and set mistakes
Using get for a required field and hiding malformed data.
Checking a value with value in mapping and accidentally searching keys.
Using a mutable list, dictionary, or set as a key or set member.
Changing a dictionary's size while iterating over a live view.
Assuming a shallow copy duplicates nested mutable values.
Depending on set order in displayed output or tests.
Reversing the operands of set difference and getting the opposite result.
Build a learning-path audit
Use the notebook below to count enrollments by language, find missing required skills, identify extra skills, and produce sorted output. Add duplicate enrollments and confirm that counts change while the learned-skills set remains unique.
Predict the counts dictionary before running the program.
Explain why brackets are appropriate for the required learner name.
Reverse required - learned and explain the different meaning.
Add an invalid blank language and reject it before counting.
Confirm that every displayed set-derived list is sorted.
Lesson review
You can now model named data with dictionaries, distinguish required and optional fields, iterate and merge mappings safely, count repeated values, represent uniqueness with sets, and express group relationships with set algebra. Complete the quick checks and scored quiz before continuing to strings, paths, and files.
RUNNABLE PYTHON NOTEBOOK
Build a learning-path audit
Count repeated enrollments, compare required and learned skills, and produce deterministic output. Change the records and verify both missing-data and duplicate behavior.
defenrollment_counts(enrollments:list[str])->dict[str,int]:
counts:dict[str,int]={}for language in enrollments:
normalized = language.strip().lower()ifnot normalized:raise ValueError("language must not be blank")
counts[normalized]= counts.get(normalized,0)+1return counts
defskill_audit(required:set[str], learned:set[str])->dict[str,list[str]]:return{"completed":sorted(required & learned),"missing":sorted(required - learned),"extra":sorted(learned - required),}
learner ={"name":"Amina","enrollments":["Python","HTML","python","CSS"],"learned_skills":{"html","python","git"},}
required_skills ={"html","css","python"}print("Learner:", learner["name"])print("Enrollments:", enrollment_counts(learner["enrollments"]))print("Audit:", skill_audit(required_skills, learner["learned_skills"]))assert enrollment_counts(["Python","python"])=={"python":2}assert skill_audit({"python","css"},{"python"})["missing"]==["css"]
OUTPUT
Press Run code to execute this Python program in your browser.
QUICK CHECK
Test what you learned
Which dictionary method returns a fallback when a genuinely optional key is absent?
QUICK CHECK
Test what you learned
Which set operator returns members present in the left set but absent from the right?
QUICK CHECK
Test what you learned
Which immutable set type can be used as a dictionary key?
KNOWLEDGE QUIZ
Check your mappings-and-sets mental model
Choose an answer for every question, then check the explanations. The goal is not to memorize syntax; it is to predict what Python will do and why.