What is a Dictionary in Python?
A complete beginner-friendly guide to Python Dictionaries — covering creation, key-value pairs, methods, nested dictionaries, dictionary comprehension, hashing internals, merging, common errors, and why dictionaries are Python's most-used data structure.
Last Updated
March 2026
Read Time
28 min
Level
Beginner
What is a Dictionary in Python?
A dictionary in Python is a built-in data structure that stores data as key-value pairs. Instead of accessing items by numeric position like a list, you access items in a dictionary using a unique, descriptive key. Every key maps to exactly one value, and that value can be anything — a number, string, list, another dictionary, or even a function.
Dictionaries are written using curly braces {} with each entry separated by a colon: {"name": "Aman", "age": 25}. Here, "name" and "age" are keys, while "Aman" and 25 are their corresponding values. This structure mirrors real-world lookups — a phone book, an English dictionary, or a database record — where you look something up by a name, not by its position in a list.
Like sets, dictionaries are built on a hash table internally. When you write my_dict["name"], Python hashes the key "name" and jumps directly to the memory slot storing its value — giving O(1) average time complexity for lookups, insertions, and deletions, regardless of how large the dictionary grows. This is the single biggest reason dictionaries are used so heavily throughout the Python language and standard library.
A crucial detail that changed the language: starting with Python 3.7, dictionaries officially preserve insertion order as a guaranteed language feature (it was an implementation detail in 3.6). This means iterating over a dictionary today returns keys in the exact order they were added — a behaviour many other languages' hash maps do not offer.
In short: a dictionary is Python's tool for storing labelled, fast-lookup data — anywhere you would naturally say "give me the value for this name" rather than "give me the third item", a dictionary is the right structure. It is arguably the single most important and most-used data structure in the entire Python language — even Python's own internals, like object attributes and namespaces, are implemented using dictionaries.
How to Create a Dictionary in Python
Python offers several ways to build a dictionary, each suited to different situations. Here are the five you'll use most often.
1. Using Curly Braces {}
student = {"name": "Riya", "age": 21, "course": "B.Tech"}
print(student)
print(type(student))Output
{'name': 'Riya', 'age': 21, 'course': 'B.Tech'} <class 'dict'>2. Using the dict() Constructor
The dict() constructor is useful when your keys are valid variable names — you can pass them directly as keyword arguments, without quotes.
student = dict(name="Riya", age=21, course="B.Tech")
print(student) # {'name': 'Riya', 'age': 21, 'course': 'B.Tech'}3. Creating an Empty Dictionary
Unlike sets, dictionaries do not have a naming trap here — {} genuinely creates an empty dictionary. This is actually the reverse situation of Python sets, where {} defaults to dict precisely because dict is the more common, default use of curly braces.
empty = {}
print(type(empty)) # <class 'dict'> — this really is a dict4. From a List of Tuples — dict()
pairs = [("a", 1), ("b", 2), ("c", 3)]
d = dict(pairs)
print(d) # {'a': 1, 'b': 2, 'c': 3}5. Dictionary Comprehension
Just like list and set comprehension, Python supports building a dictionary in a single expressive line.
squares = {x: x**2 for x in range(6)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}Important rule: dictionary keys must be unique and hashable (immutable) — strings, numbers, and tuples all qualify. Values, on the other hand, can be absolutely anything, including lists, other dictionaries, or duplicates of each other.
Key Characteristics of Python Dictionaries
Dictionaries have their own distinct rules that separate them from lists, tuples, and sets. Here are the ten most important ones to internalise.
Every item is stored as a key mapped to a value — you retrieve data by key, not by numeric position.
Since Python 3.7, dictionaries officially guarantee that keys keep the order in which they were inserted when you iterate over them.
If you assign a value to a key that already exists, the old value is simply overwritten — a dictionary can never have two identical keys.
Only immutable types — strings, numbers, and tuples — are valid keys. Lists and other dictionaries cannot be used as keys.
Unlike keys, values have no restrictions — they can be strings, numbers, lists, other dictionaries, functions, or even objects.
You can add, update, or delete key-value pairs after the dictionary is created — the dictionary itself can grow, shrink, and change.
Retrieving a value by key runs in O(1) average time thanks to hashing — regardless of how many items the dictionary holds.
You cannot access my_dict[0] expecting 'the first item' — indexing a dict always means looking up a key, not a position.
A dictionary value can itself be another dictionary, letting you model deeply structured, tree-like data such as JSON.
CPython implements dictionaries using an open-addressing hash table combined with a separate insertion-order array — the technology that also powers Python sets.
How Python Looks Up a Dictionary Value — Flowchart
Every time you write my_dict[key], Python runs the key through a precise internal lookup pipeline before returning a value. The flowchart below traces that exact process, and also shows what happens when the key doesn't exist.
Code Execution Flow — from source to output
Key insight: this is exactly why dictionary keys must be hashable and immutable — if a key's hash could change after insertion, Python would look in the wrong bucket entirely and silently fail to find data that is actually there.
Accessing and Modifying Dictionary Values
📖 Reading Values
- ▶
my_dict[key]— returns the value for key, raisesKeyErrorif the key doesn't exist. - ▶
my_dict.get(key)— returns the value for key, orNone(no error) if the key doesn't exist. - ▶
my_dict.get(key, default)— returns a custom fallback value instead of None when the key is missing.
student = {"name": "Riya", "age": 21}
print(student["name"]) # Riya
print(student.get("grade")) # None — no error
print(student.get("grade", "N/A")) # N/A — custom default✏️ Adding and Updating Values
student["grade"] = "A" # adds a new key
student["age"] = 22 # overwrites existing key's value
student.update({"city": "Patna", "age": 23}) # updates multiple keys at once
print(student)🗑️ Removing Values
- ▶
del my_dict[key]— deletes the key-value pair, raisesKeyErrorif key doesn't exist. - ▶
my_dict.pop(key)— removes key and returns its value, raisesKeyErrorif missing (unless a default is given). - ▶
my_dict.popitem()— removes and returns the last inserted key-value pair as a tuple (LIFO order). - ▶
my_dict.clear()— removes every key-value pair, leaving an empty dictionary.
del student["city"]
grade = student.pop("grade", "N/A") # safe removal with default
last_item = student.popitem() # removes most recently added pair
student.clear()
print(student) # {}Complete Python Dictionary Methods — Cheat Sheet
Here is every commonly used dictionary method in one reference table, organised by what it does.
Iterating Over a Dictionary
Dictionaries offer three distinct "views" for iteration — over keys, over values, or over both together. Since Python 3.7, all three respect the guaranteed insertion order.
scores = {"Aman": 88, "Zara": 95, "Kabir": 74}
for key in scores: # iterates over keys by default
print(key)
for value in scores.values(): # iterates over values only
print(value)
for key, value in scores.items(): # iterates over both together
print(f"{key} scored {value}").items() is by far the most commonly used pattern in real code — it lets you unpack the key and value directly in the loop header, avoiding a separate lookup like scores[key] inside the loop body.
Nested Dictionaries
A dictionary value can itself be another dictionary — this is called nesting, and it's the foundation of how Python represents structured data such as JSON API responses, configuration files, and database records.
company = {
"name": "Tech Sustainify",
"founder": {
"name": "Ashish",
"location": "India"
},
"employees": [
{"name": "Riya", "role": "Developer"},
{"name": "Zara", "role": "Designer"}
]
}
print(company["founder"]["name"]) # Ashish
print(company["employees"][0]["role"]) # DeveloperWhen accessing deeply nested keys that might not exist, chaining .get() calls avoids crashing your program: company.get("founder", {}).get("email", "N/A") safely returns "N/A" instead of raising a KeyError if "email" is missing.
Dictionary Comprehension — A Deeper Look
Dictionary comprehension follows the pattern {key_expr: value_expr for item in iterable if condition}, letting you build a dictionary from any iterable in a single readable line.
- ▶
Inverting a dictionary — {v: k for k, v in original.items()} swaps every key with its value, useful for reverse lookups.
- ▶
Filtering entries — {k: v for k, v in scores.items() if v >= 90} keeps only key-value pairs that meet a condition.
- ▶
Building from two lists — {k: v for k, v in zip(names, ages)} pairs up two parallel lists into a dictionary.
- ▶
Transforming values — {k: v.upper() for k, v in data.items()} applies a transformation to every value while keeping the keys unchanged.
scores = {"Aman": 88, "Zara": 95, "Kabir": 74}
toppers = {k: v for k, v in scores.items() if v >= 85}
print(toppers) # {'Aman': 88, 'Zara': 95}
reversed_lookup = {v: k for k, v in scores.items()}
print(reversed_lookup) # {88: 'Aman', 95: 'Zara', 74: 'Kabir'}Merging Dictionaries in Python
Python has evolved several ways to merge two dictionaries. Knowing all of them helps you read code written across different Python versions.
defaults = {"theme": "light", "font_size": 12}
user_prefs = {"font_size": 16}
# Python 3.9+ merge operator
final_settings = defaults | user_prefs
print(final_settings) # {'theme': 'light', 'font_size': 16}In every merge method above, when the same key appears in both dictionaries, the value from the right-hand (or later) dictionary wins. This is why user_prefs overrides defaults for font_size in the example above.
Dictionary vs List vs Tuple vs Set — Comparison
Choosing the right built-in collection depends on whether you need order, uniqueness, mutability, or key-based lookup.
Advantages and Disadvantages of Python Dictionaries
Dictionaries are extraordinarily useful, but understanding their trade-offs helps you choose the right structure every time.
How Python Dictionaries Work Internally — Architecture
The diagram below shows the internal layers behind every dictionary operation — from the Python code you write, down to the compact hash table CPython maintains in memory since the 3.6 redesign.
Since Python 3.6, CPython uses a clever "compact dict" design — a sparse index array that maps hashes to positions, alongside a separate dense array that stores the actual key-value pairs in insertion order. This redesign is what made guaranteed ordering possible and reduced memory usage compared to the older implementation, a rare case of getting both benefits at once.
Dictionary Performance — Big-O Complexity Table
Understanding the time complexity of common operations helps you judge when a dictionary is the right performance choice.
The "worst case" column applies only under heavy hash collisions, which are extremely rare with Python's well-distributed hash function — this is why dictionaries are described as O(1) "on average" in virtually all practical scenarios.
Your First Python Dictionary Program
Let's combine everything into one small program — building a dictionary, reading from it safely, updating it, and looping over it, exactly the pattern you'll reuse constantly in real projects.
# A simple inventory system
inventory = {"apples": 50, "bananas": 30, "oranges": 20}
inventory["grapes"] = 15 # add a new item
inventory["bananas"] -= 10 # update existing quantity
for item, quantity in inventory.items():
print(f"{item}: {quantity} units")
print("Total items:", sum(inventory.values()))Output
apples: 50 units bananas: 20 units oranges: 20 units grapes: 15 units Total items: 105Practice This Code — Live Editor
Line-by-Line Explanation
- ▶
inventory = {...}— creates a dictionary literal mapping each fruit name (key) to its stock count (value). - ▶
inventory["grapes"] = 15— since 'grapes' doesn't exist yet, this adds a brand-new key-value pair. - ▶
inventory["bananas"] -= 10— since 'bananas' already exists, this updates its existing value instead of adding a duplicate key. - ▶
inventory.items()— returns every key-value pair, letting the loop unpack both item and quantity directly. - ▶
sum(inventory.values())— .values() extracts just the numbers, which sum() then adds together.
Common Errors and Gotchas When Using Dictionaries
These are the mistakes that trip up nearly every Python learner the first time they work with dictionaries in depth.
- ▶
KeyError on Missing Keys — my_dict["missing_key"] crashes the program if the key isn't present. Use .get() or check 'key in my_dict' first when you're unsure.
- ▶
TypeError: unhashable type: 'list' — you cannot use a list or another dictionary as a key, since both are mutable and unhashable. Use a tuple instead if you need a compound key.
- ▶
Assuming .keys() Returns a List — .keys(), .values(), and .items() return special 'view' objects, not lists. They update automatically if the dictionary changes, and support 'in' checks efficiently, but need list(...) wrapped around them if you need actual list operations like indexing.
- ▶
Mutable Default Values Shared Across Keys — using {}.fromkeys(keys, []) makes every key point to the exact same list object, so modifying one key's list unexpectedly changes them all. Use a dict comprehension instead: {k: [] for k in keys}.
- ▶
Modifying a Dictionary While Iterating — adding or removing keys inside a for loop over the same dictionary raises RuntimeError: dictionary changed size during iteration. Iterate over list(my_dict.items()) instead if you need to modify it during the loop.
- ▶
Confusing == with is for Dictionary Comparison — two separate dictionaries with identical content compare equal with ==, but are not the same object in memory, so 'is' returns False even though the data matches.
Where Are Python Dictionaries Used? — Real-World Applications
Dictionaries are arguably Python's single most-used data structure. Here is where you will actually reach for a dict in real, professional code:
- ▶
🌐 Working with JSON & APIs — every JSON object returned by a web API is automatically parsed into a Python dictionary, making dicts essential for virtually all web and API development.
- ▶
⚙️ Configuration & Settings — application settings, environment variables, and feature flags are almost always modelled as dictionaries mapping setting names to their values.
- ▶
🧮 Counting & Frequency Analysis — counting word frequency in text, votes in a poll, or occurrences of any item is a natural dictionary pattern: word_counts[word] = word_counts.get(word, 0) + 1.
- ▶
🗄️ Caching & Memoization — storing previously computed results keyed by their input arguments (a cache) avoids redoing expensive calculations, and is implemented almost universally with a dict.
- ▶
📇 Representing Records — a single student, product, or user is naturally modelled as one dictionary, with keys like 'name', 'id', and 'email' — mirroring a row in a database.
- ▶
🕸️ Graph Representation — graphs are commonly represented as a dictionary mapping each node to a list of its neighbours, powering algorithms like BFS, DFS, and shortest-path search.
- ▶
🏷️ Grouping Data — grouping a list of items by a shared attribute (e.g. grouping employees by department) is typically done by building a dictionary of lists, keyed by that attribute.
- ▶
🐍 Python's Own Internals — every object's attributes, every module's namespace, and every function's local variables in CPython are themselves implemented internally using dictionaries.
Why Should You Learn Python Dictionaries in 2026?
If you only deeply master one Python data structure, it should be the dictionary. Here's why it consistently pays off across every area of Python development:
- ▶
🌍 The Language of APIs & JSON — nearly every external data source you'll work with — REST APIs, config files, NoSQL databases — arrives as JSON, which maps directly onto Python dictionaries.
- ▶
🎯 Extremely Common in Interviews — 'count word frequency', 'group by category', and 'build a cache' are classic interview problems, and all three are solved cleanly with a dictionary.
- ▶
⚡ Massive Performance Advantage — replacing a linear search through a list with a dictionary lookup is one of the highest-impact, easiest optimisations you can make in everyday code.
- ▶
🧠 Enables Readable, Self-Documenting Code — named keys like order['total_price'] communicate intent far better than an unlabeled positional value like order[4].
- ▶
🔗 Foundation for Advanced Python — kwargs, class __dict__ attributes, namespaces, and even Python's own object model are all built on the same dictionary concept you learn here.
Python Dictionary Interview Questions — Beginner Level
These are the most frequently asked interview questions specifically about Python dictionaries. Practice explaining each answer in your own words.
Practice Questions — Test Your Knowledge of Dictionaries
Try to work out each answer yourself before revealing it — active recall is one of the fastest ways to lock in a new concept.
1. What does {"a": 1, "a": 2} evaluate to, and why?
Easy2. What is the output of len({"x": 1, "y": 2, "z": 3})?
Easy3. What error does {[1, 2]: "value"} raise, and why?
Easy4. Given d = {"a": 1, "b": 2}, what does d.setdefault("c", 3) do, and what does d look like afterward?
Medium5. Why does {}.fromkeys(["a", "b"], []) create a subtle bug if you later modify one key's list?
Medium6. How would you count how many times each word appears in a list of words, in three lines or fewer?
Medium7. What is the difference between dict1.update(dict2) and dict1 | dict2?
Hard8. Write a one-line dictionary comprehension that inverts a dictionary (swaps its keys and values), assuming all original values are unique and hashable.
HardConclusion — Why the Dictionary is Python's MVP Data Structure
The Python dictionary is, without exaggeration, the most important data structure in the entire language. It is the natural home for anything with a name or a label — a user profile, an API response, a configuration file, a word count, a cache — and its O(1) average lookup speed means it stays fast even as your data grows into the millions of entries.
At the same time, dictionaries are not a universal replacement for lists, tuples, or sets. If your data is a plain, unlabeled sequence, or you need strict positional access, a list is simpler and clearer. If you only care about uniqueness and set-theory comparisons, a set is the leaner choice. Knowing when a dictionary is genuinely the right fit — versus reaching for it out of habit — is what separates a beginner from a confident Python developer.
The next step in your Python journey is to practise converting a few of your existing list-of-tuples or parallel-list patterns into dictionaries — you'll notice your code becomes both more readable and measurably faster whenever lookups by name are involved. Continue on to Python Functions next, since dictionaries are heavily used for keyword arguments (**kwargs) and default parameter patterns. 🗂️