Lists use numbers to track items. Dictionaries use names. If you have ever wanted to store data where each value has a meaningful label instead of a position number, Python dictionaries are the tool you need. This tutorial walks you through creating, reading, updating, and looping through labeled containers from the ground up.
When you first start programming, lists are a natural way to group related pieces of data together. You put items in a list, and Python assigns each one a numbered position starting at zero. That works well for ordered sequences, but it falls apart when the position number itself carries no meaning. If you store a person's name at index 0 and their email at index 1, nothing about the number 0 tells you it represents a name. Labeled containers solve this problem by letting you attach a descriptive name to each value.
What Is a Labeled Container?
A labeled container is Python's dict type, short for dictionary. Instead of looking up items by position number, you look them up by a key -- a name you choose that describes the data. Each entry in a dictionary is a key-value pair: the key is the label, and the value is the data attached to that label.
Think of a real dictionary. You look up a word (the key) and find its definition (the value). A Python dictionary works the same way. You look up a key and Python hands back the value paired with it.
Since Python 3.7, dictionaries are guaranteed to preserve insertion order. The pairs come back in the same sequence you added them. This was an implementation detail in CPython 3.6 before becoming an official part of the language specification.
Here is a quick comparison to see the difference between a list and a dictionary storing the same student record:
# List approach — positions carry no meaning
student_list = ["Ayumi", 20, "A"]
print(student_list[0]) # "Ayumi" — but 0 tells you nothing
# Dictionary approach — keys describe each value
student_dict = {"name": "Ayumi", "age": 20, "grade": "A"}
print(student_dict["name"]) # "Ayumi" — the label says it all
The dictionary version is self-documenting. Weeks later, when you read student_dict["name"], you know immediately what that value represents without checking a comment or counting positions.
Creating Your First Dictionary
There are two common ways to create a dictionary. The first, and by far the more popular, uses curly braces with colon-separated key-value pairs:
# Curly brace syntax — the standard approach
server = {
"hostname": "web-prod-01",
"ip": "10.0.1.42",
"port": 443,
"active": True
}
print(server)
# {'hostname': 'web-prod-01', 'ip': '10.0.1.42', 'port': 443, 'active': True}
The second way uses the dict() constructor with keyword arguments. This works only when keys are valid Python identifiers (no spaces or special characters):
# dict() constructor with keyword arguments
server = dict(hostname="web-prod-01", ip="10.0.1.42", port=443, active=True)
print(server)
# {'hostname': 'web-prod-01', 'ip': '10.0.1.42', 'port': 443, 'active': True}
You can also start with an empty dictionary and add pairs later:
# Start empty, then add entries one at a time
inventory = {}
inventory["apples"] = 12
inventory["bananas"] = 6
inventory["oranges"] = 9
print(inventory)
# {'apples': 12, 'bananas': 6, 'oranges': 9}
Dictionary keys must be immutable. Strings, numbers, and tuples all work as keys. Lists and other dictionaries cannot serve as keys because they are mutable -- Python cannot guarantee their hash value stays constant.
Build a dictionary that stores a pet's name as "Luna" and species as "cat":
Reading, Adding, and Removing Data
Once a dictionary exists, you interact with it through square brackets and a handful of built-in methods. Reading a value is straightforward -- supply the key inside square brackets, and Python returns the paired value:
student = {"name": "Ayumi", "age": 20, "grade": "A"}
# Read a value by key
print(student["name"]) # Ayumi
print(student["grade"]) # A
# Safe access with .get() — returns None if key is missing
print(student.get("email")) # None
print(student.get("email", "N/A")) # N/A
Accessing a key that does not exist with square brackets raises a KeyError. Always use .get() when you are not certain a key is present.
Adding a new pair uses the same square-bracket syntax. If the key already exists, the value is updated. If it does not exist, a new entry is created:
student = {"name": "Ayumi", "age": 20, "grade": "A"}
# Add a new key-value pair
student["email"] = "ayumi@example.com"
# Update an existing value
student["grade"] = "A+"
print(student)
# {'name': 'Ayumi', 'age': 20, 'grade': 'A+', 'email': 'ayumi@example.com'}
Removing entries can be done with del or the .pop() method. The del keyword removes a pair silently, while .pop() removes it and returns the value so you can use it:
student = {"name": "Ayumi", "age": 20, "grade": "A+", "email": "ayumi@example.com"}
# Remove with del — raises KeyError if key is missing
del student["email"]
# Remove with .pop() — returns the removed value
removed_grade = student.pop("grade")
print(removed_grade) # A+
# .pop() with a default — no error if key is missing
result = student.pop("phone", "not found")
print(result) # not found
print(student)
# {'name': 'Ayumi', 'age': 20}
- Use Case
- Read, add, or update a value when you are sure the key exists (or you want to create it).
- Missing Key
- Raises a KeyError if the key does not exist when reading.
- Use Case
- Safely read a value without risking an error. Ideal for optional fields.
- Missing Key
- Returns None (or your specified default) instead of raising an error.
- Use Case
- Remove a key-value pair and capture the removed value in one step.
- Missing Key
- Raises KeyError if no default is provided. Returns the default if one is given.
- Use Case
- Remove a key-value pair when you do not need the removed value.
- Missing Key
- Raises KeyError if the key does not exist.
This code should print the user's email, but it crashes. Click the line you think is wrong.
user["email"], but the dictionary on lines 1-4 never defines an "email" key. This raises a KeyError. Either add "email": "carlos@example.com" to the dictionary, or use user.get("email", "N/A") for safe access.
How to Create and Use a Python Dictionary
Follow these five steps to go from an empty file to a working dictionary you can read, modify, and iterate through.
-
Choose your data and define key-value pairs
Decide what information you want to store and what label (key) should identify each piece of data (value). Keys must be immutable types like strings or numbers. For example, to store a student record, you might choose "name", "age", and "grade" as your keys.
-
Create the dictionary with curly braces
Write your dictionary using curly braces and colons to separate each key from its value. Separate multiple pairs with commas:
student = {"name": "Ayumi", "grade": "A", "age": 20}. -
Access values using their keys
Use square bracket notation to retrieve a value by its key:
student["name"]returns"Ayumi". Use the.get()method for safe access when you are not sure the key exists. -
Add, update, and remove entries
Add new pairs with
student["email"] = "ayumi@example.com". Update existing values the same way. Remove pairs withdel student["age"]orstudent.pop("age"). -
Loop through the dictionary
Iterate over keys, values, or both using for loops. Use
.items()to unpack key-value pairs together:for key, value in student.items(): print(key, value).
Looping Through a Dictionary
For loops and dictionaries work together naturally. When you loop directly over a dictionary, Python gives you each key one at a time. You can then use that key to grab the corresponding value:
config = {"theme": "dark", "language": "en", "font_size": 14}
# Loop over keys (default behavior)
for key in config:
print(key, "->", config[key])
# Loop over values only
for value in config.values():
print(value)
# Loop over both keys and values together
for key, value in config.items():
print(f"{key}: {value}")
The .items() method is the approach you will use the majority of the time, because it unpacks both the key and value in a single step. The .keys() and .values() methods are available when you only need one half of each pair.
Common Dictionary Methods
Beyond the basics you have already seen, Python dictionaries come with several helpful methods. Here are the ones you will reach for regularly:
colors = {"sky": "blue", "grass": "green", "sun": "yellow"}
# Check if a key exists
print("sky" in colors) # True
print("ocean" in colors) # False
# Get the number of key-value pairs
print(len(colors)) # 3
# Merge another dictionary into this one
colors.update({"ocean": "teal", "sky": "azure"})
print(colors)
# {'sky': 'azure', 'grass': 'green', 'sun': 'yellow', 'ocean': 'teal'}
# Remove all entries
colors.clear()
print(colors) # {}
# Create a shallow copy
original = {"a": 1, "b": 2}
copy = original.copy()
copy["c"] = 3
print(original) # {'a': 1, 'b': 2} — original unchanged
print(copy) # {'a': 1, 'b': 2, 'c': 3}
Notice that .update() both adds new keys and overwrites existing ones. In the example above, "sky" changed from "blue" to "azure" because the same key appeared in the dictionary passed to .update().
"Dictionaries are the building blocks of Python itself." — Python Documentation (paraphrased)
Python Learning Summary Points
- A Python dictionary is a labeled container that stores data as key-value pairs, accessed by descriptive key names rather than numbered positions.
- Create dictionaries with curly braces
{}or thedict()constructor, and add or update entries using square bracket notation. - Use
.get()for safe access that avoidsKeyError, and.pop()to remove a pair while capturing the removed value. - Loop through dictionaries with
.items()to unpack both keys and values,.keys()for just keys, or.values()for just values. - Dictionary keys must be immutable types (strings, numbers, tuples), while values can be any Python object with no restrictions.
- Since Python 3.7, dictionaries preserve insertion order, so pairs are returned in the same sequence they were added.
Dictionaries are one of the foundational data structures in Python, and understanding how to create and use them opens the door to working with configuration files, API responses, database records, and nearly every other structured data format you will encounter as you continue learning.
Frequently Asked Questions
A labeled container in Python is a dictionary, which stores data as key-value pairs. Instead of using numbered positions like a list, a dictionary lets you assign a descriptive label (the key) to each piece of data (the value), making it easy to look up information by name.
You create an empty dictionary by using empty curly braces: my_dict = {}, or by calling the dict() constructor with no arguments: my_dict = dict(). Both produce the same result.
Dictionary keys must be immutable (unchangeable) types. Strings, numbers, and tuples are valid key types. Lists and other dictionaries cannot be used as keys because they are mutable.
You access a value using square bracket notation with the key name, like my_dict["key_name"]. You can also use the .get() method, which returns None (or a default value you specify) instead of raising an error when the key does not exist.
A list stores items in a numbered sequence accessed by integer index positions (0, 1, 2, etc.), while a dictionary stores items as labeled key-value pairs accessed by descriptive keys. Lists are ordered collections, and dictionaries (since Python 3.7) preserve insertion order while providing fast key-based lookups.
No. Each key in a dictionary must be unique. If you assign a value to a key that already exists, the new value replaces the old one rather than creating a second entry with the same key.
Assign a value to a new key using square bracket notation: my_dict["new_key"] = "new_value". If the key does not exist, Python creates it. If it already exists, the value is updated.
Use a for loop. Looping directly over the dictionary iterates through its keys. To loop through both keys and values together, use the .items() method: for key, value in my_dict.items().
Using square bracket notation with a missing key raises a KeyError. To avoid this, use the .get() method, which returns None by default or a fallback value you provide as a second argument.
Yes. Since Python 3.7, dictionaries are guaranteed to maintain the order in which key-value pairs were inserted. This was an implementation detail in CPython 3.6 and became part of the official language specification in Python 3.7.