DocsHub
Data Structures

Dictionaries

Learn how to store, access, and work with key-value pairs in Python using dictionaries.

Dictionaries

A dictionary stores data as key-value pairs. Instead of accessing items by position like a list, you access them by a meaningful name — the key.

Think of it like a real dictionary. You look up a word (the key) and get its definition (the value). You do not flip through every page — you go straight to the word you want.

person = {
    "name": "Ali",
    "age": 22,
    "city": "Lahore"
}

print(person["name"])   # Ali
print(person["age"])    # 22

Creating a dictionary

# empty dictionary
data = {}

# dictionary with values
student = {
    "name": "Ali",
    "age": 22,
    "grade": "A"
}

# using dict()
student = dict(name="Ali", age=22, grade="A")

Keys must be unique and immutable — strings, numbers, and tuples work as keys. Lists do not.

Values can be anything — strings, numbers, lists, other dictionaries, anything.

profile = {
    "name": "Ali",
    "scores": [88, 92, 79],       # list as a value
    "address": {                   # dictionary as a value
        "city": "Lahore",
        "country": "Pakistan"
    }
}

Accessing values

Use the key inside square brackets:

student = {"name": "Ali", "age": 22, "grade": "A"}

print(student["name"])    # Ali
print(student["grade"])   # A

If the key does not exist, Python raises a KeyError:

print(student["email"])   # KeyError: 'email'

get() — safe access

get() returns the value if the key exists, and None if it does not — no error:

print(student.get("name"))     # Ali
print(student.get("email"))    # None

You can also provide a default value if the key is missing:

print(student.get("email", "No email provided"))
# No email provided

Always use get() when you are not sure if a key exists. It prevents your program from crashing with a KeyError.


Adding and updating items

student = {"name": "Ali", "age": 22}

# add a new key
student["email"] = "ali@example.com"

# update an existing key
student["age"] = 23

print(student)
# {'name': 'Ali', 'age': 23, 'email': 'ali@example.com'}

If the key already exists, it updates the value. If it does not exist, it adds it.


update() — add or update multiple items at once

student = {"name": "Ali", "age": 22}

student.update({"age": 23, "city": "Lahore", "grade": "A"})

print(student)
# {'name': 'Ali', 'age': 23, 'city': 'Lahore', 'grade': 'A'}

Removing items

pop() — remove by key and return the value

student = {"name": "Ali", "age": 22, "grade": "A"}

removed = student.pop("grade")
print(removed)    # A
print(student)    # {'name': 'Ali', 'age': 22}

If the key does not exist, pop() raises a KeyError — unless you provide a default:

student.pop("email", None)   # no error, returns None

del — remove by key

student = {"name": "Ali", "age": 22, "grade": "A"}

del student["grade"]
print(student)   # {'name': 'Ali', 'age': 22}

popitem() — remove the last inserted item

student = {"name": "Ali", "age": 22, "grade": "A"}

last = student.popitem()
print(last)      # ('grade', 'A')
print(student)   # {'name': 'Ali', 'age': 22}

clear() — remove everything

student.clear()
print(student)   # {}

Checking if a key exists

student = {"name": "Ali", "age": 22}

print("name" in student)     # True
print("email" in student)    # False
print("email" not in student) # True

Always check before accessing a key directly if you are not sure it exists:

if "email" in student:
    print(student["email"])
else:
    print("No email on file.")

keys(), values(), items()

These three methods give you different views of the dictionary:

keys() — all the keys

student = {"name": "Ali", "age": 22, "city": "Lahore"}

print(student.keys())
# dict_keys(['name', 'age', 'city'])

values() — all the values

print(student.values())
# dict_values(['Ali', 22, 'Lahore'])

items() — all key-value pairs as tuples

print(student.items())
# dict_items([('name', 'Ali'), ('age', 22), ('city', 'Lahore')])

Looping over a dictionary

Loop over keys:

student = {"name": "Ali", "age": 22, "city": "Lahore"}

for key in student:
    print(key)

Output:

name
age
city

Loop over values:

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

Output:

Ali
22
Lahore

Loop over key-value pairs — the most common:

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

Output:

name: Ali
age: 22
city: Lahore

setdefault() — get a value or set it if missing

setdefault() returns the value for a key if it exists. If it does not exist, it adds it with the default value you provide:

student = {"name": "Ali", "age": 22}

email = student.setdefault("email", "not set")
print(email)     # not set
print(student)   # {'name': 'Ali', 'age': 22, 'email': 'not set'}

# key already exists — just returns the value, does not change it
name = student.setdefault("name", "unknown")
print(name)      # Ali

Nested dictionaries

A dictionary can contain other dictionaries as values. This is great for representing structured data:

users = {
    "ali": {
        "age": 22,
        "city": "Lahore",
        "scores": [88, 92, 79]
    },
    "sara": {
        "age": 25,
        "city": "Karachi",
        "scores": [95, 91, 88]
    }
}

print(users["ali"]["city"])          # Lahore
print(users["sara"]["scores"][0])    # 95

Loop over nested dictionaries:

for username, info in users.items():
    print(f"\nUser: {username}")
    print(f"  Age: {info['age']}")
    print(f"  City: {info['city']}")
    print(f"  Average score: {sum(info['scores']) / len(info['scores']):.1f}")

Output:

User: ali
  Age: 22
  City: Lahore
  Average score: 86.3

User: sara
  Age: 25
  City: Karachi
  Average score: 91.3

Merging dictionaries

Using update():

defaults = {"theme": "light", "language": "en", "notifications": True}
user_prefs = {"theme": "dark", "language": "ur"}

defaults.update(user_prefs)
print(defaults)
# {'theme': 'dark', 'language': 'ur', 'notifications': True}

Using the | operator (Python 3.9+):

defaults = {"theme": "light", "language": "en"}
user_prefs = {"theme": "dark"}

merged = defaults | user_prefs
print(merged)   # {'theme': 'dark', 'language': 'en'}

The right dictionary wins when keys conflict.


A real example

A simple word frequency counter:

text = "the quick brown fox jumps over the lazy dog the fox"
words = text.split()

frequency = {}

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

# sort by frequency, highest first
sorted_words = sorted(frequency.items(), key=lambda x: x[1], reverse=True)

for word, count in sorted_words:
    print(f"{word}: {count}")

Output:

the: 3
fox: 2
quick: 1
brown: 1
jumps: 1
over: 1
lazy: 1
dog: 1

frequency.get(word, 0) + 1 — if the word exists, get its count and add 1. If it does not exist, start from 0 and add 1.


Summary

MethodWhat it does
d[key]Access value — raises KeyError if missing
d.get(key, default)Access value safely — returns default if missing
d[key] = valueAdd or update a key
d.update({...})Add or update multiple keys
d.pop(key)Remove key and return its value
del d[key]Remove a key
d.popitem()Remove and return the last item
d.clear()Remove all items
d.keys()All keys
d.values()All values
d.items()All key-value pairs as tuples
d.setdefault(key, val)Get value or set it if missing
key in dCheck if key exists

On this page