What is a Python dictionary?
A Python dictionary is a built-in mapping type that stores values under keys. It’s implemented with an internal hash table that maps each hashable key to a memory location for its value. Dictionaries are the go-to structure for lookups and mappings in Python. We can think of them as fast “maps” or associative arrays.
- Python dictionary is a mapping of key → value implemented as a hash table (fast lookups).
- Keys must be unique and hashable (immutable types like str, int, tuple).
- From Python 3.7+ insertion order of dict is guaranteed.
- Typical dictionary operations (lookup, insert, delete) are O(1) average-time.
# Example: simple dictionary
person = {'name': 'Alice', 'age': 30,
'languages': ['Python', 'SQL']}
print(person)
Output:
{'name': 'Alice', 'age': 30, 'languages': ['Python', 'SQL']}

Creating a dictionary
You can create dictionaries using literal {}, the dict() constructor, from sequences of pairs, or using comprehensions. Use literal notation for readability; dict() is handy when converting from other mappings or sequences.
# Literal notation
d1 = {1: 'Python', 2: 'For', 3: 'Learn'}
# dict() constructor using keyword arguments
d2 = dict(a='Python', b='For', c='Learn')
# dict() from sequence of pairs
d3 = dict([(1, 'Python'), (2, 'For')])
# Empty dict
d4 = {}
print(d1)
print(d2)
print(d3)
print(d4)
Accessing items in Dictionary — [] vs .get()
Direct access d[key] raises KeyError if the key is missing. d.get(key, default) returns a default instead and is safer for optional keys.
d = {'name': 'Prajjwal', 1: 'Python', (1, 2): [1, 2, 4]}
# Direct access (KeyError if missing)
print(d['name'])
# Safe access using get()
print(d.get('name'))
print(d.get('missing', 'default-value'))
Prajjwal Prajjwal default-value
Adding & updating dictionary items
Assigning a value to d[key] inserts or updates. update() merges another mapping (or iterable of pairs) into the dict.
d = {1: 'Python', 2: 'For', 3: 'Python'}
# Add new key
d['age'] = 22
# Update existing key
d[1] = 'Python dict'
# Bulk update
d.update({'x': 100, 'y': 200})
print(d)
{1: 'Python dict', 2: 'For', 3: 'Python', 'age': 22, 'x': 100, 'y': 200}
Removing dictionary items
You can remove items with del, pop(key), popitem(), or clear entire dict with clear(). Note: since Python 3.7 popitem() removes the last-inserted key-value pair (LIFO), whereas older versions removed an arbitrary item.
d = {1: 'Python', 2: 'For', 3: 'Python', 'age': 22}
# del by key
del d['age']
# pop returns the value
val = d.pop(1)
print("popped value:", val)
# popitem returns and removes last-inserted pair (3.7+)
pair = d.popitem()
print("popitem:", pair)
# clear all
d.clear()
print("after clear:", d)
popped value: Python
popitem: (3, 'Python') remaining: {2: 'For'}
after clear: {}
Iteration – Loop over Dictionary – keys(), values(), items()
dict.keys(), dict.values(), and dict.items() produce view objects. Iterating for k, v in d.items() is the idiomatic way to access both key and value.
d = {'a': 1, 'b': 2, 'c': 3}
print(list(d.keys()))
print(list(d.values()))
print(list(d.items()))
for k, v in d.items():
print(k, '->', v)
Output:
['a', 'b', 'c'] [1, 2, 3] [('a', 1), ('b', 2), ('c', 3)] a -> 1 b -> 2 c -> 3
Dictionary comprehension
Comprehensions let you build dictionaries compactly and readably — perfect for transforming lists or producing lookup tables (e.g., invert index or frequency mapping).
fruits = ['apple', 'banana', 'cherry']
index_map = {fruit: idx for idx, fruit in enumerate(fruits)}
even_squares = {n: n * n for n in range(10) if n % 2 == 0}
print(index_map)
print(even_squares)
Output:
index_map: {'apple': 0, 'banana': 1, 'cherry': 2} even_squares: {0: 0, 2: 4, 4: 16}
Nested dictionaries
Dictionaries often model JSON-style nested data. Access nested fields with chained indexing or safe patterns (get() with defaults). Use setdefault() or defaultdict patterns to create nested entries safely.
nested = {
'user1': {'name': 'Alice', 'roles': ['admin', 'user']},
'user2': {'name': 'Bob', 'roles': ['user']}
}
# Direct access
print(nested['user1']['name'])
# Safe access for missing keys
print(nested.get('user3', {}).get('name', 'Unknown'))
# Initialize nested safely
nested.setdefault('user3', {})['name'] = 'Charlie'
print(nested['user3'])
Output:
Alice Unknown {'name': 'Charlie'}
Merging dictionaries
Merge two dicts into a new dict using | (Python 3.9+) or {**a, **b} for older versions. update() mutates the left-hand dict.
a = {'x': 1, 'y': 2}
b = {'y': 20, 'z': 3}
# Python 3.9+: new merged dict
merged = a | b
print("merged:", merged)
# Unpacking merge (pre-3.9)
merged2 = {**a, **b}
print("merged2:", merged2)
# In-place
a.update(b)
print("a after update:", a)
Output:
merged: {'x': 1, 'y': 20, 'z': 3} merged2: {'x': 1, 'y': 20, 'z': 3} a_copy after update: {'x': 1, 'y': 20, 'z': 3}
Common helpers: defaultdict, Counter, OrderedDict
defaultdict simplifies grouping and nested initialization.
Counter solves counting/frequency problems.
OrderedDict is historically used to preserve order on older Python.
built-in dict preserves insertion order in modern Python.
from collections import defaultdict, Counter, OrderedDict # defaultdict for grouping groups = defaultdict(list) groups['k'].append(1) groups['k'].append(2) print(dict(groups)) # Counter for frequency counting cnt = Counter(['a', 'b', 'a', 'c', 'b', 'a']) print(cnt) # OrderedDict (historical use) od = OrderedDict() od['x'] = 1 od['y'] = 2 print(list(od.keys()))
Output:
defaultdict: {'k': [1, 2]} Counter: Counter({'a': 3, 'b': 2, 'c': 1}) OrderedDict keys: ['x', 'y']
Python Dict ↔ JSON
Dictionaries map directly to JSON objects. Use json.dumps() to serialize and json.loads() to parse. Remember booleans and null map to True/False/None.
import json
d = {'name': 'Alice', 'age': 30, 'active': True}
json_str = json.dumps(d)
print("json:", json_str)
d_back = json.loads(json_str)
print("dict:", d_back)
Performance & complexity
Dictionaries use hashing which gives average O(1) time for lookup, insert, and delete. In adversarial or degenerate cases (many hash collisions or extreme rehashing) costs degrade.
Example: many O(1) inserts and lookups (illustrative, not a benchmark)
d = {}
for i in range(100000):
d[i] = i * 2
print("lookup example:", d[50000])
Hashable keys Dictionary
-> Keys must be hashable (objects with an immutable hash value). Common mistakes:
-> Using mutable types (lists, dicts) as keys → TypeError.
-> Using floats with NaN — NaN != NaN, but hash behavior can be surprising.
# Hashable vs unhashable
valid = {(1, 2): 'pair', 'name': 'Alice', 10: 'ten'}
print(valid)
try:
bad = {[1, 2]: 'list-key'} # raises TypeError
except TypeError as e:
print("Error:", e)
Invert mapping (values may map to multiple keys)
m = {'a': 1, 'b': 2, 'c': 1}
inv = {}
for k, v in m.items():
inv.setdefault(v, []).append(k)
print("inverted:", inv)
Build index
fruits = ['apple', 'banana', 'cherry']
index_map = {i: v for i, v in enumerate(fruits)}
print(index_map)
Time and Space Complexity of Python Dictionary
| Operation | Average Complexity |
|---|---|
| Lookup | O(1) |
| Insert / Update | O(1) |
| Delete | O(1) |
| Iterate | O(n) |
| Space | O(n) |
Python Dictionary – Summary
Creation: {}, dict(), comprehensions
Access: d[key] (raises) vs d.get(key, default)
Update: d[key] = v, d.update(mapping)
Remove: del, pop, popitem, clear
Iteration: for k, v in d.items()
Tools: defaultdict, Counter, OrderedDict
JSON: json.dumps() / json.loads()
Performance: average O(1) operations, requires hashable keys.
FAQs — Python Dictionary
What is a Dictionary in Python?
A dictionary in Python is an unordered, mutable collection used to store data as key–value pairs. Keys must be unique and immutable (like strings, numbers, or tuples).
person = {"name": "Alice", "age": 25, "city": "London"}
How to create a Dictionary in Python?
You can create a dictionary using curly braces {} or the dict() constructor:
my_dict = {'a': 1, 'b': 2}
another_dict = dict(x=10, y=20)
How to access values in a Python Dictionary?
Use the key name inside square brackets or the get() method:
person = {"name": "Bob", "age": 30}
print(person["name"])
print(person.get("age"))
How to add or update values in a Python Dictionary?
Assign a value to a key directly. If the key exists, it updates the value; otherwise, it adds a new key-value pair:
person["age"] = 31
person["country"] = "UK"
How to remove items from a Python Dictionary?
Use pop(), del, or clear() to remove items:
person.pop("age")
del person["name"]
person.clear()
How to iterate through a Python Dictionary?
You can loop through keys, values, or both:
for key in person:
print(key, person[key])
for k, v in person.items():
print(k, v)
What are common methods available in Python Dictionary?
keys()– Returns all keysvalues()– Returns all valuesitems()– Returns key-value pairsget()– Retrieves value safelypop()– Removes by keyupdate()– Merges another dictionaryclear()– Removes all items
How to merge two dictionaries in Python?
Use the update() method or the | merge operator (Python 3.9+):
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
# Method 1
dict1.update(dict2)
# Method 2 (Python 3.9+)
merged = dict1 | dict2
How to check if a key exists in a Python Dictionary?
Use the in keyword:
if "name" in person:
print("Key found!")
How to copy a Dictionary in Python?
Use copy() or the dict() constructor to create a shallow copy:
dict_copy = person.copy()
dict_clone = dict(person)
What is the difference between a Python List and a Dictionary?
A list stores values in an ordered sequence accessed by index, while a dictionary stores key–value pairs accessed by key.
my_list = [10, 20, 30]
my_dict = {"a": 10, "b": 20, "c": 30}
Can a Python Dictionary have duplicate keys?
No. Each key in a dictionary must be unique. If you use a duplicate key, the last assignment will overwrite the previous value.