Python gives you several ways to store data, but few are as practical or widely used as the dictionary. At its core, a dictionary is a collection of key-value pairs — a structure that lets you label your data and retrieve it by name instead of by position.
When you first start writing Python, lists feel like the natural answer for storing data. They are straightforward and they work well for sequences. But as soon as your data has structure — a name, an age, a score tied to a player — lists start to show their limits. You end up guessing which index holds which piece of information, and the code becomes harder to read. Dictionaries solve that problem by giving every value a name.
What Is a Key-Value Pair?
A key-value pair is exactly what it sounds like: two pieces of data that belong together. The key is a label, and the value is the data attached to that label. In Python, a dictionary holds one or more of these pairs, separated by commas and enclosed in curly braces.
# A simple dictionary with three key-value pairs
user = {
"name": "Alice",
"age": 28,
"active": True
}
print(user["name"]) # Alice
print(user["age"]) # 28
Each key in a dictionary must be unique and immutable — strings and integers are the most common choices. Values can be anything: a number, a string, a list, another dictionary, or even a function. The key is always written first, followed by a colon, then the value.
Keys must be hashable. Strings, integers, floats, and tuples are valid keys. Lists and dictionaries cannot be used as keys because they are mutable and Python cannot compute a stable hash for them.
Python dictionaries have maintained insertion order since version 3.7, meaning the pairs appear in the order they were added. If you are running Python 3.6 or older, do not rely on this behavior.
Build a valid Python dictionary that stores a username of "dev42" under the key "user":
{}, not square brackets [] (those are for lists) or parentheses () (those are for tuples or function calls). Inside the braces, the key "user" is separated from its value "dev42" by a colon.
Lists vs. Dictionaries: When Each Makes Sense
Lists and dictionaries both store collections of data, but they answer different questions. A list answers "what is at position N?" A dictionary answers "what is the value for this name?" The choice depends on how you need to access your data.
Consider storing information about a player in a game. With a list, the positions are meaningless on their own — you have to remember that index 0 is the name, index 1 is the score, and index 2 is the level. With a dictionary, the meaning is built into the structure.
# List approach — you must remember what each index means
player_list = ["Reza", 4200, 7]
print(player_list[1]) # 4200 — but what does index 1 represent?
# Dictionary approach — the key tells you exactly what the value is
player_dict = {
"name": "Reza",
"score": 4200,
"level": 7
}
print(player_dict["score"]) # 4200 — no ambiguity
Dictionaries also give you much faster lookups when your collection is large. Internally, Python uses a hash table, so finding a key takes roughly the same time whether the dictionary has ten items or ten thousand. Lists require scanning items one by one until a match is found.
- List
- By integer index —
items[0] - Dictionary
- By named key —
data["name"]
- List
- O(n) — scanning each item in order
- Dictionary
- O(1) average — direct hash table lookup
- List
- Ordered sequences of similar items — a list of scores, a queue of tasks
- Dictionary
- Structured records with named fields — user profiles, config settings, API responses
- List
- Allows duplicate values —
[1, 1, 2]is valid - Dictionary
- Keys must be unique — assigning to an existing key overwrites its value
If you find yourself storing parallel lists — one for names, another for scores — that is a signal to switch to a list of dictionaries. Each dictionary becomes one record, and the relationship between fields stays intact.
Reading, Writing, and Updating Dictionary Data
Once you have a dictionary, three operations cover the vast majority of everyday use: reading a value, adding or updating a value, and safely checking whether a key exists before reading it.
Reading values
Square bracket notation retrieves a value directly. If the key is not present, Python raises a KeyError. The safer option is the .get() method, which returns None by default — or a fallback value you provide.
config = {"timeout": 30, "retries": 3}
# Direct access — raises KeyError if key is missing
print(config["timeout"]) # 30
# Safe access with .get() — returns None if key is missing
print(config.get("host")) # None
# Safe access with a fallback value
print(config.get("host", "localhost")) # localhost
Adding and updating values
Assigning to a key adds it if it does not exist, or overwrites it if it does. There is no separate "add" method — the same syntax handles both cases.
settings = {"theme": "dark"}
# Add a new key
settings["language"] = "en"
print(settings) # {'theme': 'dark', 'language': 'en'}
# Update an existing key
settings["theme"] = "light"
print(settings) # {'theme': 'light', 'language': 'en'}
"Dictionaries are Python's most versatile data structure for mapping relationships between data." — Python Software Foundation documentation, paraphrased
This code tries to look up a user's email address. One line contains a bug that will cause a KeyError at runtime. Click the line you think is wrong, then hit check.
user["phone"] with user.get("phone", "N/A"). The key "phone" does not exist in the dictionary, so square bracket access raises a KeyError. The .get() method handles missing keys gracefully and returns the fallback value instead of crashing.
How to Use Key-Value Pairs in Python
These four steps cover the core workflow for working with dictionaries in Python. Each step builds on the previous one, taking you from creating a dictionary to iterating over its contents.
-
Create a dictionary with curly brace syntax
Write a variable name, assign it a pair of curly braces, and place your
key: valuepairs inside separated by commas. String keys should be wrapped in quotes. For an empty dictionary, writemy_dict = {}ormy_dict = dict(). -
Access values using bracket notation or .get()
Use
my_dict["key"]for direct access. If the key may not exist, usemy_dict.get("key")to avoid aKeyError. Supply a second argument to.get()as a default:my_dict.get("key", "default_value"). -
Add or update key-value pairs
Assign to a key directly:
my_dict["new_key"] = "new_value". If the key already exists its value is overwritten. If it does not exist, Python creates it. To merge another dictionary in, use the.update()method. -
Iterate over a dictionary
Use
for key, value in my_dict.items()to loop through all pairs. Use.keys()to iterate keys only, or.values()for values only. This pattern is common when processing records or building output from structured data.
# Putting it all together
inventory = {"apples": 10, "bananas": 5, "oranges": 8}
# Add a new item
inventory["grapes"] = 12
# Update an existing item
inventory["bananas"] = 7
# Iterate over all key-value pairs
for item, count in inventory.items():
print(f"{item}: {count}")
# apples: 10
# bananas: 7
# oranges: 8
# grapes: 12
Python Learning Summary Points
- A Python dictionary stores data as key-value pairs inside curly braces. Keys must be unique and immutable; values can be any data type.
- Dictionaries provide O(1) average-time lookups through hash table internals, making them far more efficient than lists for named data retrieval at scale.
- Use bracket notation for direct access and the
.get()method when a key might be absent — this preventsKeyErrorand makes code more resilient. - Dictionaries are the natural choice when your data has labeled fields, such as user profiles, configuration objects, API responses, or any structured record.
- Since Python 3.7, dictionaries preserve insertion order, so you can rely on pairs appearing in the sequence they were added.
Key-value pairs are one of those foundational ideas that show up everywhere in Python — from reading JSON data to configuring libraries to managing state in applications. Knowing when and how to use a dictionary will make your code more readable, more efficient, and easier to maintain as your programs grow.
Frequently Asked Questions
A key-value pair is a unit of data in a Python dictionary where a unique key maps to a corresponding value. You write it as key: value inside curly braces, such as {'name': 'Alice'}. The key is used to look up the value directly, without scanning every item.
A list stores items in order and you access them by their position (index). A dictionary stores items as key-value pairs and you access values by a named key. Use a list when order matters and items are positional; use a dictionary when items have meaningful labels and you need fast, direct access.
You can create a dictionary using curly brace literal syntax: my_dict = {'key': 'value'}. You can also use the dict() constructor: my_dict = dict(key='value'). An empty dictionary is created with {} or dict().
Access a value by placing its key in square brackets: my_dict['key']. To avoid a KeyError when the key might not exist, use the .get() method: my_dict.get('key'), which returns None if the key is absent.
Dictionary keys must be hashable — meaning immutable types like strings, integers, floats, and tuples are valid keys. Mutable types such as lists or other dictionaries cannot be used as keys because they are not hashable.
Dictionaries use a hash table internally. When you look up a key, Python computes a hash value and jumps directly to the location in memory. Lists require iterating through each item to find a match. This gives dictionaries O(1) average lookup time versus O(n) for lists.
The existing value is overwritten. Python dictionaries do not raise an error for duplicate key assignments — the most recent assignment wins. If you need to track multiple values per key, store a list as the value.
The .get() method retrieves the value for a given key without raising a KeyError if the key does not exist. It returns None by default, or a fallback value you specify as a second argument: my_dict.get('missing_key', 'default').
Since Python 3.7, dictionaries maintain insertion order — items appear in the order they were added. Prior to 3.7, dictionaries were unordered. If you need a guaranteed ordered mapping with additional methods, the collections module provides OrderedDict.
Use a dictionary when your data has labeled fields, when you need fast direct access by a meaningful name, or when you are modeling a real-world entity with named attributes. Use a list when you have a sequence of similar items where position or order is what matters.