Ad – 728Γ—90
πŸ“¦ Data Structures

Python Dictionaries – The Complete Guide

Dictionaries are Python's premier key-value data structure. Where lists use integer positions to find items, dictionaries use meaningful keys β€” like a real-world dictionary where you look up "Python" to find its definition. They are unordered (insertion-ordered since Python 3.7), mutable, and blazing-fast for lookups. This lesson covers creating dictionaries, accessing and modifying data, all built-in dict methods, iteration patterns, nested dictionaries, and dictionary comprehensions.

⏱️ 28 min read 🎯 Beginner–Intermediate πŸ“… Updated 2026

Creating Dictionaries

A dictionary is created with curly braces {}. Each entry is a key: value pair separated by a colon, and pairs are separated by commas.

Python
# Literal syntax (most common)
person = {
    "name": "Alice",
    "age": 30,
    "city": "New York",
    "is_student": False
}

# Empty dictionary
empty_dict = {}

# Using dict() constructor
car = dict(make="Toyota", model="Camry", year=2022)

# From a list of pairs
pairs = [("a", 1), ("b", 2), ("c", 3)]
from_pairs = dict(pairs)

print(person)
print(car)
print(from_pairs)
print(f"Number of keys: {len(person)}")
β–Ά Output
{'name': 'Alice', 'age': 30, 'city': 'New York', 'is_student': False} {'make': 'Toyota', 'model': 'Camry', 'year': 2022} {'a': 1, 'b': 2, 'c': 3} Number of keys: 4
πŸ’‘
What Can Be a Key?

Dictionary keys must be immutable: strings, integers, floats, booleans, and tuples are valid keys. Lists and other dicts cannot be keys because they're mutable. String keys are by far the most common in real-world code.

Accessing Values

Access values using the key in square brackets. If the key doesn't exist, it raises a KeyError. Use the .get() method to safely access keys that may not exist.

Python
product = {
    "name": "Laptop",
    "brand": "TechBrand",
    "price": 999.99,
    "in_stock": True
}

# Direct access (raises KeyError if missing)
print(product["name"])      # Laptop
print(product["price"])     # 999.99

# Safe access with .get() - returns None if missing
print(product.get("brand"))          # TechBrand
print(product.get("color"))          # None
print(product.get("color", "N/A"))   # N/A  (default value)

# Check if a key exists
if "in_stock" in product:
    print("Stock info available")

# Check if key NOT in dict
if "discount" not in product:
    print("No discount key")
β–Ά Output
Laptop 999.99 TechBrand None N/A Stock info available No discount key

Adding and Updating Keys

Python
student = {"name": "Bob", "age": 20}

# Add a new key
student["grade"] = "A"
student["major"] = "Computer Science"
print(student)

# Update an existing key (overwrites the value)
student["age"] = 21
print("After update:", student)

# Update multiple keys at once with .update()
student.update({
    "year": 2,
    "gpa": 3.8,
    "age": 22   # also updates existing key
})
print("After .update():", student)
β–Ά Output
{'name': 'Bob', 'age': 20, 'grade': 'A', 'major': 'Computer Science'} After update: {'name': 'Bob', 'age': 21, 'grade': 'A', 'major': 'Computer Science'} After .update(): {'name': 'Bob', 'age': 22, 'grade': 'A', 'major': 'Computer Science', 'year': 2, 'gpa': 3.8}

Deleting Keys

Python
config = {
    "host": "localhost",
    "port": 8080,
    "debug": True,
    "timeout": 30,
    "retries": 3
}

# del - raises KeyError if key not found
del config["debug"]
print(config)

# .pop() - removes and returns the value; optional default
timeout = config.pop("timeout")
print(f"Removed timeout: {timeout}")

missing = config.pop("nonexistent", "default_val")
print(f"Pop missing key: {missing}")

# .popitem() - removes and returns the last inserted pair (Python 3.7+)
last_key, last_val = config.popitem()
print(f"Popped last item: {last_key} = {last_val}")

# .clear() - empties the dictionary
temp = {"a": 1, "b": 2}
temp.clear()
print("After clear:", temp)
β–Ά Output
{'host': 'localhost', 'port': 8080, 'timeout': 30, 'retries': 3} Removed timeout: 30 Pop missing key: default_val Popped last item: retries = 3 After clear: {}
Ad – 336Γ—280

Key Dictionary Methods

MethodDescriptionReturns
d.keys()All keysdict_keys view
d.values()All valuesdict_values view
d.items()All key-value pairs as tuplesdict_items view
d.get(k, default)Value for key k, or defaultvalue or default
d.update(other)Merge another dict into dNone
d.pop(k, default)Remove key k and return valuevalue or default
d.popitem()Remove and return last item(key, value) tuple
d.setdefault(k, default)Return value; insert default if missingvalue
d.clear()Remove all itemsNone
d.copy()Shallow copynew dict

Iterating Over Dictionaries

Python
scores = {
    "Alice": 95,
    "Bob": 82,
    "Carol": 91,
    "David": 78
}

# Iterate keys (default)
print("Students:")
for name in scores:
    print(f"  {name}")

# Iterate values
print("\nScores:")
for score in scores.values():
    print(f"  {score}")

# Iterate key-value pairs (most common)
print("\nFull report:")
for name, score in scores.items():
    grade = "Pass" if score >= 80 else "Fail"
    print(f"  {name:<8}: {score}  ({grade})")

# Find the top scorer
top = max(scores, key=lambda name: scores[name])
print(f"\nTop scorer: {top} with {scores[top]}")
β–Ά Output
Students: Alice Bob Carol David Scores: 95 82 91 78 Full report: Alice : 95 (Pass) Bob : 82 (Pass) Carol : 91 (Pass) David : 78 (Fail) Top scorer: Alice with 95

setdefault() – Powerful Grouping Pattern

setdefault(key, default) returns the value for a key if it exists, or inserts the key with the default value and returns it. This is perfect for building dictionaries of lists (grouping items).

Python
# Group words by their first letter
words = ["apple", "avocado", "banana", "blueberry", "cherry", "apricot", "coconut"]

grouped = {}
for word in words:
    letter = word[0]
    grouped.setdefault(letter, []).append(word)

for letter, group in sorted(grouped.items()):
    print(f"  {letter}: {group}")
β–Ά Output
a: ['apple', 'avocado', 'apricot'] b: ['banana', 'blueberry'] c: ['cherry', 'coconut']

Nested Dictionaries

Dictionary values can themselves be dictionaries. This is used frequently to represent structured data like records, configurations, and API responses.

Python
company = {
    "name": "TechCorp",
    "employees": {
        "E001": {
            "name": "Alice",
            "role": "Engineer",
            "salary": 95000
        },
        "E002": {
            "name": "Bob",
            "role": "Manager",
            "salary": 110000
        },
        "E003": {
            "name": "Carol",
            "role": "Designer",
            "salary": 85000
        }
    }
}

# Access nested values
print(company["name"])
print(company["employees"]["E001"]["name"])   # Alice
print(company["employees"]["E002"]["salary"])  # 110000

# Update a nested value
company["employees"]["E003"]["salary"] = 90000

# Add a new nested record
company["employees"]["E004"] = {
    "name": "David",
    "role": "DevOps",
    "salary": 100000
}

# Iterate nested dict
print("\nAll employees:")
for emp_id, info in company["employees"].items():
    print(f"  {emp_id}: {info['name']} ({info['role']}) β€” ${info['salary']:,}")
β–Ά Output
TechCorp Alice 110000 All employees: E001: Alice (Engineer) β€” $95,000 E002: Bob (Manager) β€” $110,000 E003: Carol (Designer) β€” $90,000 E004: David (DevOps) β€” $100,000
⚠️
Accessing Missing Nested Keys

Chaining bracket access on a nested dict raises KeyError if any level is missing. Use .get() at each level: d.get("a", {}).get("b", default). Or use the collections.defaultdict for auto-creating nested structures.

Dictionary Comprehensions

Like list comprehensions, dict comprehensions let you build dictionaries in a single line using the syntax {key: value for item in iterable}.

Python
# Square each number as a key-value pair
squares = {n: n**2 for n in range(1, 6)}
print(squares)   # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# Filter: only include even squares
even_squares = {n: n**2 for n in range(1, 11) if n % 2 == 0}
print(even_squares)   # {2: 4, 4: 16, 6: 36, 8: 64, 10: 100}

# Invert a dictionary (swap keys and values)
original = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in original.items()}
print(inverted)   # {1: 'a', 2: 'b', 3: 'c'}

# Build a word-length mapping
words = ["python", "is", "awesome", "programming"]
word_lengths = {word: len(word) for word in words}
print(word_lengths)
β–Ά Output
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25} {2: 4, 4: 16, 6: 36, 8: 64, 10: 100} {1: 'a', 2: 'b', 3: 'c'} {'python': 6, 'is': 2, 'awesome': 7, 'programming': 11}

Practical Real-World Example

Python
def word_frequency(text):
    """Count how many times each word appears in a text."""
    words = text.lower().split()
    freq = {}
    for word in words:
        # Remove basic punctuation
        word = word.strip(".,!?;:")
        freq[word] = freq.get(word, 0) + 1
    return freq

text = """Python is great. Python is easy to learn.
Python is used for data science and web development.
Learning Python is fun!"""

freq = word_frequency(text)

# Sort by frequency (most common first)
sorted_freq = dict(sorted(freq.items(), key=lambda item: item[1], reverse=True))

print("Word frequencies:")
for word, count in list(sorted_freq.items())[:8]:
    bar = "β–ˆ" * count
    print(f"  {word:<12}: {count}  {bar}")
β–Ά Output
Word frequencies: python : 4 β–ˆβ–ˆβ–ˆβ–ˆ is : 4 β–ˆβ–ˆβ–ˆβ–ˆ great : 1 β–ˆ easy : 1 β–ˆ to : 2 β–ˆβ–ˆ learn : 1 β–ˆ used : 1 β–ˆ for : 1 β–ˆ

πŸ‹οΈ Practical Exercise

  1. Create a dictionary representing a book (title, author, year, pages, genre). Print each field using a for loop over .items().
  2. Write code that safely retrieves a key that might not exist, providing a meaningful default value using .get().
  3. Given a list of numbers, use a dict comprehension to create a dictionary where each number is a key and its cube is the value.
  4. Write a function count_chars(text) that returns a dictionary of character frequencies for letters only (ignore spaces and punctuation).
  5. Create a nested dictionary of 3 cities, each with keys for population, country, and timezone. Write code to print a formatted summary of each city.

πŸ”₯ Challenge

Build a simple inventory management system using a dictionary. Each product name is a key; each value is a nested dict with price, quantity, and category. Implement functions: add_product(inventory, name, price, qty, category), sell(inventory, name, qty) (reduce quantity; warn if insufficient stock), restock(inventory, name, qty), and report(inventory) (print a table with total values per item and overall inventory value). Test all functions with sample data.

Interview Questions on Python Dictionaries

  • What types can be used as dictionary keys? Why can't lists be keys?
  • What is the difference between dict[key] and dict.get(key)?
  • How do you merge two dictionaries? Describe two ways (including Python 3.9+ syntax).
  • What does dict.setdefault(key, default) do? Give a real-world use case.
  • What is the time complexity of a dictionary lookup in Python? Why is it so fast?
  • How do you iterate over a dictionary's key-value pairs simultaneously?
  • What is a dictionary comprehension? Write one that inverts a dictionary.
  • How are Python dictionaries ordered? Was this always the case?

πŸ“‹ Summary

  • Dictionaries store key-value pairs in curly braces {}. Keys must be immutable.
  • Access values with dict[key] (raises KeyError if missing) or dict.get(key, default) (safe).
  • Add or update a key with assignment: dict[key] = value. Use .update() to merge multiple pairs.
  • Delete with del dict[key], dict.pop(key) (returns value), or dict.popitem() (returns last pair).
  • .keys(), .values(), and .items() return live views of the dict's data.
  • .setdefault(key, default) is ideal for grouping patterns.
  • Nested dicts can represent complex structured data; chain bracket access carefully.
  • Dict comprehensions {k: v for ...} create dicts concisely from any iterable.
  • Since Python 3.7, dicts maintain insertion order.

Frequently Asked Questions

Are Python dictionaries ordered? +

Since Python 3.7, dictionaries maintain insertion order as a language guarantee (it was an implementation detail in CPython 3.6). If you iterate a dict, items come out in the order they were added. For Python 3.6 and earlier you needed collections.OrderedDict for guaranteed ordering.

How do you merge two dictionaries in Python? +

Several ways: (1) d1.update(d2) β€” modifies d1 in place. (2) {**d1, **d2} β€” creates a new merged dict (Python 3.5+). (3) d1 | d2 β€” new merged dict (Python 3.9+). (4) d1 |= d2 β€” merge d2 into d1 in place (Python 3.9+). In all cases, if both dicts share a key, the right-side value wins.

Why are dictionary lookups so fast? +

Dictionaries are implemented as hash tables. When you store a key, Python computes a hash of it (a fixed-size integer) and uses that hash to determine where to store the value. Retrieval computes the same hash and goes directly to that location β€” O(1) average time, independent of dictionary size. This is why dict keys must be hashable (immutable).

Can a dictionary have duplicate keys? +

No. Dictionary keys are unique. If you write d = {"a": 1, "a": 2}, the second value silently overwrites the first, giving {"a": 2}. Python won't raise an error β€” so be careful when building dicts programmatically that you don't accidentally overwrite important data.

What is the difference between dict.items() and dict.keys()? +

dict.keys() returns a view of all keys. dict.items() returns a view of all key-value pairs as 2-tuples. dict.values() returns just the values. These are view objects β€” they reflect the dict in real time, so if you modify the dict, the views update. Convert to list() if you need a snapshot.