Python Dictionaries Tutorial: Syntax, Methods and Worked Examples

Learn how Python dictionaries store, retrieve and transform key-value data through runnable examples, common traps and one complete marks-processing task.

KnowledgeGate Team

Exam prep & CS education

Updated 11 Aug 20266 min read

A list can store scores, but it does not naturally answer questions such as “What is Dev's score?” or “How many pens remain?” A Python dictionary connects each meaningful key to a value, making that lookup direct, and that lookup takes about the same time whether the dictionary holds four pairs or forty thousand. Counters, lookup tables, JSON records and program settings all rest on that one structure. Lists and strings usually come first in a complete Python learning path; dictionaries are the step where data starts carrying names instead of positions.

What is a dictionary in Python?

Consider this object:

marks = {"Anika": 72, "Dev": 88, "Ira": 72, "Kabir": 95}

It has four string keys, four integer values and four key-value pairs. marks["Dev"] evaluates to 88. The value 72 appears twice, which is valid because dictionary values may repeat. Keys must be unique.

Keys must be hashable, meaning a key cannot change after the pair is stored. Strings, numbers and tuples of hashable items qualify; a list does not. The official Python Dictionaries documentation states the same restriction in terms of immutable types. Dictionaries also preserve insertion order, so the pairs above are visited in the order Anika, Dev, Ira and Kabir.

Use a list such as [72, 88, 72, 95] when position identifies each item. Use the dictionary when names such as "Anika" and "Dev" are the identities.

A key-to-value map linking Anika, Dev, Ira and Kabir to 72, 88, 72 and 95, with two arrows reaching 72 to show values can repeat.

Creating dictionaries and reading values safely

Here are three common construction forms and their results:

stock = {"pen": 12, "notebook": 5, "eraser": 9}

profile = {}
profile["name"] = "Meera"
print(profile)  # {'name': 'Meera'}

colours = dict([("red", 3), ("blue", 7)])
print(colours)  # {'red': 3, 'blue': 7}
print(stock["pen"])           # 12
print(stock.get("marker"))    # None
print(stock.get("marker", 0)) # 0
print("eraser" in stock)      # True

The in expression checks keys, not values. Use square brackets when a missing key indicates a programming error. Use get() when absence is expected and a fallback such as 0 has a clear meaning.

Adding, updating and removing pairs

Assignment adds a new key or updates an existing one. pop() removes a pair and returns its value.

stock = {"pen": 12, "notebook": 5, "eraser": 9}

stock["marker"] = 6
print(stock)  # {'pen': 12, 'notebook': 5, 'eraser': 9, 'marker': 6}

stock["pen"] = 15
print(stock)  # {'pen': 15, 'notebook': 5, 'eraser': 9, 'marker': 6}

removed = stock.pop("eraser")
print(stock)    # {'pen': 15, 'notebook': 5, 'marker': 6}
print(removed)  # 9

Each row below starts from its own fresh dictionary, so the results do not chain:

Method

Example

Exact result

update()

d = {"a": 1}; d.update({"a": 4, "b": 2})

d is {'a': 4, 'b': 2}

pop()

d = {"a": 1, "b": 2}; d.pop("a")

Returns 1; d is {'b': 2}

popitem()

d = {"a": 1, "b": 2}; d.popitem()

Returns ('b', 2); d is {'a': 1}

clear()

d = {"a": 1}; d.clear()

d is {}

setdefault()

groups = {}; groups.setdefault("Python", []).append("Asha")

groups is {'Python': ['Asha']}

A copy lets you change this simple mapping without changing the original:

copy = stock.copy()
copy["pen"] = 20
print(copy["pen"])   # 20
print(stock["pen"])  # 15

Looping through dictionaries and building new ones

You can loop over keys, values or complete pairs:

marks = {"Anika": 72, "Dev": 88, "Ira": 72, "Kabir": 95}

for name in marks:
    print(name)

for score in marks.values():
    print(score)

for name, score in marks.items():
    print(name, score)

The paired loop prints Anika 72, Dev 88, Ira 72 and Kabir 95, each on its own line, in insertion order. A dictionary comprehension can filter or transform those pairs:

qualified = {name: score for name, score in marks.items() if score >= 80}
print(qualified)  # {'Dev': 88, 'Kabir': 95}

boosted = {name: score + 5 for name, score in marks.items()}
print(boosted)  # {'Anika': 77, 'Dev': 93, 'Ira': 77, 'Kabir': 100}

The second comprehension creates a new dictionary and does not change marks. Order is a separate question: to rebuild the mapping highest score first, write dict(sorted(marks.items(), key=lambda pair: pair[1], reverse=True)), which gives {'Kabir': 95, 'Dev': 88, 'Anika': 72, 'Ira': 72}. Anika stays ahead of Ira because Python's sort is stable and keeps the original order for equal values.

Fully worked example: process a class score record

This complete program updates one score, adds a student, removes a withdrawn record, filters qualified students, and calculates the average and topper.

marks = {"Anika": 72, "Dev": 88, "Ira": 72, "Kabir": 95}

marks["Anika"] += 5
marks["Leena"] = 81
withdrawn_score = marks.pop("Ira")

qualified = {name: score for name, score in marks.items() if score >= 80}
average = sum(marks.values()) / len(marks)
topper = max(marks, key=marks.get)

print("Withdrawn score:", withdrawn_score)
print("Final marks:", marks)
print("Qualified:", qualified)
print("Average:", average)
print("Topper:", topper)

The exact output is:

Withdrawn score: 72
Final marks: {'Anika': 77, 'Dev': 88, 'Kabir': 95, 'Leena': 81}
Qualified: {'Dev': 88, 'Kabir': 95, 'Leena': 81}
Average: 85.25
Topper: Kabir

Anika's score becomes 72 + 5 = 77. After Ira is removed, the final total is 77 + 88 + 95 + 81 = 341. There are 4 records, so the average is 341 / 4 = 85.25. Kabir's 95 is the largest value.

Try two changes. First, change the qualification threshold to 85; the result keeps Dev and Kabir. Second, add "Maya": 95, find top_score = max(marks.values()), then use [name for name, score in marks.items() if score == top_score]. The result is ['Kabir', 'Maya'].

Pipeline of the worked program: updated marks Anika 77, Dev 88, Kabir 95, Leena 81 give qualified students, average 85.25 and topper Kabir.

Common dictionary errors and why they happen

  • stock["stapler"] raises KeyError if the key is absent, because square-bracket access is a strict lookup with no fallback of its own. Use stock.get("stapler", 0) only when zero is a genuine answer rather than a convenient one.

  • {["CS", 9]: "room"} raises TypeError: unhashable type: 'list', because a list can be edited after insertion and its hash would then be stale. Use the hashable tuple {("CS", 9): "room"}.

  • {"id": 101, "id": 205} becomes {'id': 205}. The later duplicate silently overwrites the earlier value.

Deleting entries while iterating over the same dictionary changes its size and raises a runtime error:

for key in stock:
    del stock[key]  # RuntimeError

Iterate over a separate list of keys instead:

for key in list(stock):
    del stock[key]

If you simply want an empty dictionary, stock.clear() states the intention more directly. Also remember that sorted(marks) returns a list of sorted keys, not a sorted dictionary. The binary trees and binary search trees guide is a useful next comparison because dictionary lookup and ordered tree traversal solve different problems.

How coding tests check dictionaries

Coding tests and interviews reuse the same three dictionary tasks: trace a mutation, pick a valid key, or count frequencies. Frequency counting in particular is the standard first move on word, character and duplicate-detection problems in Coding & DSA rounds.

  1. d = {"a": 2, "b": 3}; d["a"] += d.get("c", 4); print(d) prints {'a': 6, 'b': 3}.

  2. Of ("CS", 9) and ["CS", 9], the tuple is the valid dictionary key.

  3. This loop converts the words into {'gate': 2, 'python': 3, 'code': 1}:

words = ["gate", "python", "gate", "code", "python", "python"]
counts = {}

for word in words:
    counts[word] = counts.get(word, 0) + 1

Trace each line with the current dictionary beside it. That habit catches missed updates and incorrect default values.

The short version

Dictionaries map unique, hashable keys to values. Use get() when absence is expected. Assignment adds or updates a pair. Use items() when you need each key with its value. Comprehensions filter or transform a mapping without touching the original. When you must delete while looping, iterate over list(d) rather than the dictionary itself.

For structured language practice, continue with the Python Programming course. Then use the DSA Using Python course to apply mappings alongside other data structures.