Skip to main content
Python•Last Updated : 20 Oct 2026
~45 min read

Dictionaries and Sets in Python

Key-value lookup with dictionaries: creating, reading safely, updating, iterating, counting and grouping, nested records and comprehensions. Then sets for uniqueness, fast membership and set algebra.

Dictionaries: looking things up by key

A list answers "what is at position 3?". Often you want to ask "what is the phone number for Ada?" instead. A dictionary (dict) stores key → value pairs and finds a value by its key directly, without scanning, however large the dictionary is.

Write a dictionary with curly braces and key: value pairs. Read a value with square brackets: ages["Ada"]. Keys are unique: assigning to an existing key replaces its value.

Looking up a key that does not exist raises KeyError. When a key may be missing, use get(key), which returns None, or get(key, default), which returns your default.

Definition: Dictionary

A mutable mapping from unique, hashable keys to values. Lookup, insertion and deletion by key take constant time on average, and iteration follows insertion order.

Note

`in` on a dictionary checks keys, not values. Use `value in d.values()` to search the values (which is a slow scan).

PythonCreating and reading a dictionary
1capitals = {"France": "Paris", "Japan": "Tokyo", "Kenya": "Nairobi"}
2print(capitals["Japan"])
3print(len(capitals))
4print(capitals.get("Peru"))
5print(capitals.get("Peru", "unknown"))
6print("Kenya" in capitals, "Nairobi" in capitals)
Output
Tokyo
3
None
unknown
True False

Adding, changing and removing entries

Dictionaries are mutable:

  • d[key] = value adds a new pair or replaces the value of an existing key.
  • d.update(other) copies every pair from another dictionary, overwriting matching keys.
  • d.pop(key) removes a key and returns its value; d.pop(key, default) does not fail when the key is missing.
  • del d[key] removes a key (and raises KeyError if it is absent).

Since Python 3.7, dictionaries remember insertion order: iterating gives keys in the order they were first added. Replacing a value keeps the key's position.

PythonChanging a dictionary
1stock = {"apples": 12, "pears": 4}
2stock["plums"] = 9
3stock["apples"] -= 5
4stock.update({"pears": 10, "figs": 3})
5print(stock)
6sold_out = stock.pop("plums")
7print(sold_out, stock)
8print(stock.pop("kiwis", 0))
9del stock["figs"]
10print(stock)
Output
{'apples': 7, 'pears': 10, 'plums': 9, 'figs': 3}
9 {'apples': 7, 'pears': 10, 'figs': 3}
0
{'apples': 7, 'pears': 10}

Looping over a dictionary

Three views give you what you need to loop over:

  • d.keys(): the keys (also what you get from for key in d)
  • d.values(): the values
  • d.items(): (key, value) pairs, best unpacked directly in the for line

To process entries in a particular order, sort the items: sorted(d.items(), key=lambda kv: kv[1]) sorts by value. Do not add or remove keys while looping over a dictionary; Python raises RuntimeError. Loop over list(d) if you need to delete as you go.

Pythonkeys, values and items
1prices = {"coffee": 3.2, "tea": 2.5, "cake": 4.0}
2for item in prices:
3 print(item, end=" ")
4print()
5print(sum(prices.values()))
6for item, price in prices.items():
7 print(f"{item:<8}{price:>6.2f}")
8cheapest = min(prices.items(), key=lambda kv: kv[1])
9print("Cheapest:", cheapest)
Output
coffee tea cake 
9.7
coffee    3.20
tea       2.50
cake      4.00
Cheapest: ('tea', 2.5)

Counting and grouping

Two patterns account for a large share of real dictionary use.

Counting: start each key at 0 the first time you see it. counts[x] = counts.get(x, 0) + 1 does that in one line.

Grouping: collect items into a list per key. groups.setdefault(key, []).append(item) creates the empty list the first time and appends every time.

The standard library packages both patterns: collections.Counter counts an iterable in one call and collections.defaultdict(list) creates missing lists automatically. Learn the manual versions first, since they work everywhere and make the idea clear.

PythonCounting words and grouping by first letter
1words = "the cat sat on the mat with the hat".split()
2
3counts = {}
4for w in words:
5 counts[w] = counts.get(w, 0) + 1
6print(counts)
7
8by_letter = {}
9for w in words:
10 by_letter.setdefault(w[0], []).append(w)
11print(by_letter)
12
13from collections import Counter
14print(Counter(words).most_common(2))
Output
{'the': 3, 'cat': 1, 'sat': 1, 'on': 1, 'mat': 1, 'with': 1, 'hat': 1}
{'t': ['the', 'the', 'the'], 'c': ['cat'], 's': ['sat'], 'o': ['on'], 'm': ['mat'], 'w': ['with'], 'h': ['hat']}
[('the', 3), ('cat', 1)]

Records and nested data

A dictionary is a natural record: named fields instead of positions. A list of such dictionaries is a table, and dictionaries can contain lists and other dictionaries. This is exactly the shape of JSON data that web services send and receive, which the files lesson uses.

Read nested values one level at a time: user["address"]["city"]. When an intermediate level might be missing, chain get calls with an empty dictionary as the default.

PythonA list of records
1students = [
2 {"name": "Ada", "scores": [91, 88], "address": {"city": "London"}},
3 {"name": "Alan", "scores": [79, 85], "address": {}},
4]
5for s in students:
6 average = sum(s["scores"]) / len(s["scores"])
7 city = s["address"].get("city", "unknown")
8 print(f"{s['name']}: {average:.1f} ({city})")
9
10best = max(students, key=lambda s: sum(s["scores"]))
11print("Best:", best["name"])
Output
Ada: 89.5 (London)
Alan: 82.0 (unknown)
Best: Ada

What can be a key

Dictionary lookup works by hashing: Python turns the key into a number that points to where the value is stored. That only works if the key never changes, so keys must be hashable, which in practice means immutable: numbers, strings, booleans, None and tuples of these. Lists and dictionaries cannot be keys and raise TypeError: unhashable type.

Values have no restrictions; they can be anything, including lists and other dictionaries.

PythonTuple keys for a grid
1board = {}
2board[(0, 0)] = "X"
3board[(1, 2)] = "O"
4print(board.get((1, 2)), board.get((2, 2), "."))
5print(hash("abc") == hash("abc"))
Output
O .
True

Dictionary comprehensions

A dictionary comprehension builds a dictionary in one expression: {key_expr: value_expr for item in iterable if condition}. It is handy for transforming or filtering an existing dictionary, or for building a lookup table from a list.

Inverting a dictionary ({v: k for k, v in d.items()}) only works when the values are unique; otherwise later keys overwrite earlier ones.

PythonBuilding dictionaries in one line
1names = ["ada", "grace", "linus"]
2lengths = {n: len(n) for n in names}
3print(lengths)
4
5prices = {"tea": 2.5, "cake": 4.0, "water": 1.0}
6print({k: v for k, v in prices.items() if v >= 2})
7print({k: round(v * 1.2, 2) for k, v in prices.items()})
8print({v: k for k, v in lengths.items()})
Output
{'ada': 3, 'grace': 5, 'linus': 5}
{'tea': 2.5, 'cake': 4.0}
{'tea': 3.0, 'cake': 4.8, 'water': 1.2}
{3: 'ada', 5: 'linus'}

Sets: unique values and fast membership

A set is an unordered collection of unique, hashable values, written with curly braces: {"python", "sql"}. (An empty set is set(), because {} is an empty dictionary.)

Sets are the right tool for three jobs:

  1. Removing duplicates: set(items).
  2. Fast membership tests: x in some_set takes constant time on average, while x in some_list checks every item.
  3. Set algebra: a | b (union), a & b (intersection), a - b (difference) and a ^ b (in exactly one).

Sets have no order and no indexes. When you print them or need a stable order, convert with sorted(s).

Caution

Never rely on the order in which a set prints or iterates; it can differ between runs and Python versions. Sort first when order matters.

PythonUniqueness and set operations
1tags = ["python", "web", "python", "sql", "web"]
2unique = set(tags)
3print(len(tags), len(unique))
4print(sorted(unique))
5
6team_a = {"python", "sql", "go"}
7team_b = {"python", "rust", "sql"}
8print(sorted(team_a | team_b))
9print(sorted(team_a & team_b))
10print(sorted(team_a - team_b))
11print(sorted(team_a ^ team_b))
12
13unique.add("css")
14unique.discard("web")
15print("css" in unique, "web" in unique)
Output
5 3
['python', 'sql', 'web']
['go', 'python', 'rust', 'sql']
['python', 'sql']
['go']
['go', 'rust']
True False

Choosing a collection

Pick the structure by the question your program asks most often.

list, tuple, dict or set?

StructureOrderedMutableDuplicatesBest for
listYesYesYesA sequence of items you add to, sort and loop over
tupleYesNoYesFixed records, multiple return values, keys
dictInsertion orderYesUnique keysLooking up a value by a key, counting, grouping
setNoYesNoUniqueness, fast membership, set algebra
Key Takeaways & Summary
  • •Use d.get(key, default) when a key may be missing.
  • •Iterate with for key, value in d.items().
  • •Count with counts.get(x, 0) + 1 and group with setdefault(key, []).append(x).
  • •Sets remove duplicates and make membership checks fast, but have no order.

Check your understanding

Suggested Quiz
Question 1 of 5

What does `print({"a": 1}.get("b", 0))` print?

Practice

Count word frequencies with a dictionary, compare two lists with set operations, and merge nested configuration dictionaries recursively.

[Problem]

Word Frequency Counter

Reveal Solution & Analysis
Model Solution
[Problem]

Common Elements

Reveal Solution & Analysis
Model Solution
[Problem]

Dictionary Deep Merge

Reveal Solution & Analysis
Model Solution

Quick Syntax & Reference Sheet

Concept / RuleSyntax / Usage
Create / readd = {"a": 1}; d["a"]; d.get("b", 0)
Add / update / removed["b"] = 2; d.update(other); d.pop("a")
Loop over pairsfor key, value in d.items():
Countcounts[x] = counts.get(x, 0) + 1
Groupgroups.setdefault(k, []).append(item)
Dict comprehension{k: v * 2 for k, v in d.items()}
Set operationsa | b, a & b, a - b, a ^ b
Empty sets = set()

Common Pitfalls & Developer Mistakes

✕ Mistake 1:

Reading a missing key with d[key]

Why it happens: It raises KeyError.

Correction: Check with in first, or use d.get(key, default).
✕ Mistake 2:

Writing {} for an empty set

Why it happens: {} is an empty dictionary.

Correction: set()
✕ Mistake 3:

Changing a dictionary's keys while iterating over it

Why it happens: Python raises RuntimeError: dictionary changed size during iteration.

Correction: Loop over list(d) or build a new dictionary with a comprehension.
✕ Mistake 4:

Depending on set order

Why it happens: Sets are unordered; string order can differ between runs.

Correction: sorted(my_set)

Frequently Asked Questions

Why are dictionary lookups fast?

A dictionary is a hash table: the key's hash points almost directly to where the value is stored, so lookup time does not grow with the number of entries (on average).

Are dictionaries ordered?

Since Python 3.7 they keep insertion order as a language guarantee. That is not the same as sorted order; use sorted(d) for that.

When should I use Counter or defaultdict?

Whenever counting or grouping is the whole job: Counter(words).most_common(3) is shorter and clearer than the manual loop. Knowing the manual version helps when the rule is more unusual.

Hands-On Practice Problems

Article Tags:#Python#Dictionaries#Sets#Hashing#Counting
Was this lesson clear and helpful?

Discussion (0)

Sign in to ask questions and reply.
Loading discussion…
Discuss in community