Python Dictionary Methods: A Complete Guide

· 9 min read

Introduction

Dictionaries are one of Python’s most used data structures. Unlike lists, which store items by index, dictionaries store data as key-value pairs — making lookups instant regardless of how many items the dictionary contains.

Understanding dictionary methods well means writing less code, fewer bugs, and more readable Python. This guide covers every commonly used dictionary method with practical examples and real-world patterns.

All examples are tested on Python 3.12.


Creating Dictionaries

There are several ways to create a dictionary:

# Literal syntax
person = {"name": "Alice", "age": 28}

# dict() constructor with keyword arguments
person = dict(name="Alice", age=28)

# From a list of key-value pairs
person = dict([("name", "Alice"), ("age", 28)])

# Dictionary comprehension
squares = {x: x**2 for x in range(5)}
print(squares)

Expected output:

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

The literal syntax ({}) is the most common. Dictionary comprehensions — covered in more depth in the list comprehensions guide — are useful when building dictionaries from existing data.


Accessing Values

Direct Access with []

person = {"name": "Alice", "age": 28}

print(person["name"])

Expected output:

Alice

Direct access raises a KeyError if the key does not exist:

print(person["email"])

Expected output:

KeyError: 'email'

Safe Access with .get()

.get() returns None instead of raising an error when the key is missing:

print(person.get("email"))

Expected output:

None

You can also provide a custom default value:

print(person.get("email", "N/A"))

Expected output:

N/A

In most real-world code, .get() is preferred over [] when the key might not exist — it avoids crashes and eliminates the need for try/except blocks around simple lookups.


Adding and Updating Values

Adding a New Key

person["email"] = "alice@example.com"
print(person)

Expected output:

{'name': 'Alice', 'age': 28, 'email': 'alice@example.com'}

Updating an Existing Key

Assigning to an existing key overwrites the value:

person["age"] = 29
print(person["age"])

Expected output:

29

Batch Updates with .update()

.update() adds or overwrites multiple keys at once:

person.update({"age": 30, "city": "London"})
print(person)

Expected output:

{'name': 'Alice', 'age': 30, 'email': 'alice@example.com', 'city': 'London'}

You can also pass keyword arguments:

person.update(age=31, city="Paris")

.update() is useful when merging external data — for example, applying a batch of user-submitted changes to an existing record.


Removing Items

.pop() — Remove and Return a Value

person = {"name": "Alice", "age": 28, "city": "London"}

age = person.pop("age")
print(age)
print(person)

Expected output:

28
{'name': 'Alice', 'city': 'London'}

.pop() with a default value avoids KeyError when the key might not exist:

salary = person.pop("salary", 0)
print(salary)

Expected output:

0

.popitem() — Remove the Last Inserted Item

person = {"name": "Alice", "age": 28, "city": "London"}

key, value = person.popitem()
print(key, value)

Expected output:

city London

.popitem() removes items in last-in, first-out order. It is useful when processing a dictionary one item at a time.

del Statement

person = {"name": "Alice", "age": 28}

del person["age"]
print(person)

Expected output:

{'name': 'Alice'}

.clear() — Remove All Items

person.clear()
print(person)

Expected output:

{}

Checking Keys and Membership

The in Operator

person = {"name": "Alice", "age": 28}

print("name" in person)
print("salary" in person)

Expected output:

True
False

Note that in checks keys, not values. To check whether a value exists, use in person.values().

.keys(), .values(), .items()

These three methods return view objects — live windows into the dictionary’s current state:

print(person.keys())
print(person.values())
print(person.items())

Expected output:

dict_keys(['name', 'age'])
dict_values(['Alice', 28])
dict_items([('name', 'Alice'), ('age', 28)])

View objects update automatically when the dictionary changes. To get a plain list, wrap them with list():

keys = list(person.keys())

Iterating Over a Dictionary

Iterating Over Keys

person = {"name": "Alice", "age": 28, "city": "London"}

for key in person:
    print(key)

Expected output:

name
age
city

Iterating Over Values

for value in person.values():
    print(value)

Expected output:

Alice
28
London

Iterating Over Key-Value Pairs

for key, value in person.items():
    print(f"{key}: {value}")

Expected output:

name: Alice
age: 28
city: London

.items() is the most common iteration pattern in real code — it gives you both the key and value together without needing to look up the value separately.

Real-World Example: Word Frequency Counter

text = "the cat sat on the mat the cat"
words = text.split()

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

print(word_count)

Expected output:

{'the': 3, 'cat': 2, 'sat': 1, 'on': 1, 'mat': 1}

word_count.get(word, 0) returns the current count (or 0 if the word has not appeared yet), then adds 1. This is one of the most common dictionary patterns in Python.


Merging Dictionaries

Python offers three ways to merge dictionaries, each introduced in a different version:

a = {"x": 1, "y": 2}
b = {"y": 3, "z": 4}

# Method 1: .update() — modifies a in place
merged = a.copy()
merged.update(b)
print(merged)

# Method 2: ** unpacking — Python 3.5+
merged = {**a, **b}
print(merged)

# Method 3: | operator — Python 3.9+, most concise
merged = a | b
print(merged)

Expected output:

{'x': 1, 'y': 3, 'z': 4}
{'x': 1, 'y': 3, 'z': 4}
{'x': 1, 'y': 3, 'z': 4}

In all three cases, when both dictionaries contain the same key, the value from the right-hand dictionary (b) wins. If you need the left-hand values to take priority, reverse the order.

The | operator is the cleanest option for Python 3.9+. For older codebases, {**a, **b} is the standard approach.


.setdefault() — Set a Default if Missing

.setdefault() checks whether a key exists. If it does, it returns the existing value. If it does not, it inserts the key with the given default and returns that default:

person = {"name": "Alice"}

person.setdefault("email", "unknown@example.com")
print(person)

# Calling again does not overwrite the existing value
person.setdefault("email", "new@example.com")
print(person["email"])

Expected output:

{'name': 'Alice', 'email': 'unknown@example.com'}
unknown@example.com

Grouping Data with .setdefault()

The most common use case for .setdefault() is grouping items into lists:

groups = {}
data = [("fruit", "apple"), ("veggie", "carrot"), ("fruit", "banana")]

for category, item in data:
    groups.setdefault(category, []).append(item)

print(groups)

Expected output:

{'fruit': ['apple', 'banana'], 'veggie': ['carrot']}

Each time a new category appears, .setdefault() creates an empty list. Subsequent items in the same category get appended to that list.


Sorting a Dictionary

Dictionaries preserve insertion order in Python 3.7+, but they do not sort automatically. To sort by key or value, use sorted() with .items():

scores = {"Alice": 95, "Bob": 87, "Carol": 92}

# Sort by key (alphabetical)
by_key = dict(sorted(scores.items()))
print(by_key)

# Sort by value (ascending)
by_value = dict(sorted(scores.items(), key=lambda x: x[1]))
print(by_value)

# Sort by value (descending)
by_value_desc = dict(sorted(scores.items(), key=lambda x: x[1], reverse=True))
print(by_value_desc)

Expected output:

{'Alice': 95, 'Bob': 87, 'Carol': 92}
{'Bob': 87, 'Carol': 92, 'Alice': 95}
{'Alice': 95, 'Carol': 92, 'Bob': 87}

Nested Dictionaries

Dictionaries can contain other dictionaries, which is common when representing structured data like records or API responses:

employees = {
    "alice": {"age": 28, "department": "Engineering"},
    "bob": {"age": 34, "department": "Marketing"},
}

# Access a nested value
print(employees["alice"]["department"])

Expected output:

Engineering

Safe Access in Nested Dictionaries

Chaining .get() avoids errors when intermediate keys might be missing:

dept = employees.get("carol", {}).get("department", "Unknown")
print(dept)

Expected output:

Unknown

Iterating Over Nested Dictionaries

for name, info in employees.items():
    print(f"{name}: {info['department']}, age {info['age']}")

Expected output:

alice: Engineering, age 28
bob: Marketing, age 34

Common Patterns

Replace if-elif Chains with a Dictionary

Long if-elif chains are often cleaner as dictionary lookups:

# Verbose version
def get_discount(tier):
    if tier == "gold":
        return 0.2
    elif tier == "silver":
        return 0.1
    elif tier == "bronze":
        return 0.05
    else:
        return 0

# Dictionary version
def get_discount(tier):
    discounts = {"gold": 0.2, "silver": 0.1, "bronze": 0.05}
    return discounts.get(tier, 0)

Both versions produce identical results. The dictionary version is easier to extend — adding a new tier means adding one line to the dictionary, not modifying control flow.

Use collections.Counter for Counting

For the word frequency pattern shown earlier, Python’s standard library offers a more concise tool:

from collections import Counter

text = "the cat sat on the mat the cat"
word_count = Counter(text.split())

print(word_count)
print(word_count.most_common(3))

Expected output:

Counter({'the': 3, 'cat': 2, 'sat': 1, 'on': 1, 'mat': 1})
[('the', 3), ('cat', 2), ('sat', 1)]

Counter is a dictionary subclass with extra methods like .most_common(). It is the right tool whenever you are counting occurrences of items.


Quick Reference

MethodWhat It Does
d[key]Get value — raises KeyError if missing
d.get(key, default)Get value safely — returns default if missing
d.keys()View of all keys
d.values()View of all values
d.items()View of all key-value pairs
d.update(other)Add or overwrite multiple keys
d.pop(key, default)Remove and return value
d.popitem()Remove and return last inserted item
d.setdefault(key, default)Insert default if key is missing
d.copy()Shallow copy
d.clear()Remove all items
a | bMerge two dicts (Python 3.9+)

Wrap-Up

Dictionaries are central to Python — they appear in function keyword arguments, JSON data, configuration objects, caches, and countless other patterns. Knowing the full set of dictionary methods means reaching for the right tool in each situation rather than reimplementing common patterns from scratch.

For related reading, the mutable vs immutable guide explains why dictionaries behave the way they do — including why dictionary keys must be hashable and what happens when you copy a nested dictionary. For questions or future tutorial ideas, get in touch via the Contact page.