PythonDictionaries

Dictionaries

A dictionary (dict) stores data as key-value pairs. Instead of looking up a value by its numeric position, as you would with a list, you look it up by a key — a name, an id, a coordinate, anything hashable. Dictionaries are one of the most heavily used data structures in Python, powering everything from JSON payloads to function keyword arguments.

Creating a Dictionary

You can build a dict with curly-brace literal syntax using key: value pairs, or with the dict() constructor.

Python
person = {"name": "Ada", "age": 36, "language": "Python"}
print(person)   # {'name': 'Ada', 'age': 36, 'language': 'Python'}

# dict() constructor - handy with keyword arguments
person2 = dict(name="Grace", age=40, language="COBOL")
print(person2)  # {'name': 'Grace', 'age': 40, 'language': 'COBOL'}

empty = {}       # note: {} is an empty dict, not an empty set
print(type(empty))  # <class 'dict'>
Keys Must Be Hashable

A dict key must be an immutable, hashable object — strings, numbers, and tuples all qualify. Lists (and other dicts, and sets) are mutable, so Python refuses to use them as keys: if the contents of a list could change after it was used as a key, its hash value would no longer match where it was stored, silently breaking the lookup. A tuple, being immutable, has a stable hash for its lifetime and works fine.

Python
# Tuples work as keys because they're immutable
locations = {
    (40.7128, -74.0060): "New York",
    (51.5074, -0.1278): "London",
}
print(locations[(40.7128, -74.0060)])   # New York

# Lists are mutable, so they cannot be keys:
# bad = {[1, 2]: "value"}   # TypeError: unhashable type: 'list'
Accessing, Adding, Updating, and Deleting

Square-bracket syntax reads and writes a value for a given key. If the key already exists, assignment overwrites its value; if it does not, assignment creates a new entry. del removes a key entirely.

Python
inventory = {"apples": 10, "bananas": 5}

print(inventory["apples"])   # 10          -- access

inventory["cherries"] = 20   #             -- add a new key
inventory["apples"] = 15     #             -- update an existing key
print(inventory)  # {'apples': 15, 'bananas': 5, 'cherries': 20}

del inventory["bananas"]     #             -- delete a key
print(inventory)  # {'apples': 15, 'cherries': 20}
KeyError risk with []
Reading a missing key with square brackets raises `KeyError` and can crash your program. `inventory["mangoes"]` above would fail with `KeyError: 'mangoes'` since that key was never set. Use `.get()` (below) when the key might not exist.
Safer Access with .get()

The .get() method looks up a key and returns None (or a default value you supply) instead of raising an error when the key is missing.

Python
inventory = {"apples": 15, "cherries": 20}

print(inventory.get("apples"))            # 15
print(inventory.get("mangoes"))           # None -- no crash
print(inventory.get("mangoes", 0))        # 0    -- explicit default instead of None
Checking Whether a Key Exists

Use the in operator to test for a key without triggering a KeyError. This checks keys only, not values.

Python
inventory = {"apples": 15, "cherries": 20}

print("apples" in inventory)    # True
print("mangoes" in inventory)   # False
print(15 in inventory)          # False -- 15 is a value, not a key
Dictionaries Preserve Insertion Order
Note
Since Python 3.7, dictionaries guarantee that keys are iterated in the order they were first inserted. This was an implementation detail in earlier CPython versions but became an official language guarantee in 3.7, so you can safely depend on it in modern Python code.

Python
order = {}
order["first"] = 1
order["second"] = 2
order["third"] = 3

print(list(order.keys()))   # ['first', 'second', 'third'] -- insertion order preserved
Nested Dictionaries

Dictionary values can themselves be dictionaries (or lists, or any object), which is how you model structured, JSON-like data in Python.

Python
users = {
    "u1": {"name": "Ada", "roles": ["admin", "editor"]},
    "u2": {"name": "Grace", "roles": ["viewer"]},
}

print(users["u1"]["name"])          # Ada
print(users["u2"]["roles"][0])      # viewer

# Adding a new nested entry
users["u3"] = {"name": "Linus", "roles": ["contributor"]}
print(users["u3"]["name"])          # Linus

# Safely reading a deeply nested value that might not exist
roles = users.get("u4", {}).get("roles", [])
print(roles)   # []  -- no KeyError even though "u4" doesn't exist
  • Dict literals use {key: value, ...}; dict() accepts keyword arguments or an iterable of pairs.

  • Keys must be hashable (immutable): strings, numbers, and tuples work; lists, dicts, and sets do not.

  • Use .get() when a key might be missing; use [] only when you are certain the key exists.

  • Insertion order is preserved and guaranteed since Python 3.7.