100% Client-Side No Signup Python 3.7+ Free Forever

Python Dictionary Methods Cheat Sheet

The Cartographer's Map Room — 50+ dictionary methods, operations, and patterns. Search, filter by category, and copy code examples instantly. Covers built-in methods, operators, comprehensions, merging, and common patterns.

50+
Methods
9
Categories
0
Dependencies
🗺
Creating Dictionaries
6 items
{}
Returns NewBuilt-in

Literal syntax for creating an empty dictionary or a dictionary with initial key-value pairs. Fastest and most common way.

empty = {}
# {}

person = {'name': 'Alice', 'age': 30}
# {'name': 'Alice', 'age': 30}

# Mixed key types (all must be hashable):
mixed = {1: 'one', 'two': 2, (3, 4): 'tuple key'}
dict()
Returns NewBuilt-in

Constructor for creating dictionaries. Accepts keyword arguments, iterables of pairs, or mappings. Useful for dynamic creation.

empty = dict()
# {}

# From keyword arguments:
person = dict(name='Alice', age=30)
# {'name': 'Alice', 'age': 30}

# From list of tuples:
pairs = [('a', 1), ('b', 2)]
d = dict(pairs)
# {'a': 1, 'b': 2}
dict(iterable)
Returns NewBuilt-in

Create a dictionary from any iterable of key-value pairs. Common sources include zip(), enumerate(), and list comprehensions.

keys = ['a', 'b', 'c']
values = [1, 2, 3]

# From zip:
d = dict(zip(keys, values))
# {'a': 1, 'b': 2, 'c': 3}

# From enumerate:
d = dict(enumerate(['x', 'y', 'z'], start=1))
# {1: 'x', 2: 'y', 3: 'z'}
dict.fromkeys(seq, value)
Returns NewClass Method

Create a dictionary with keys from seq and all values set to value (default None). Efficient for initialization.

keys = ['a', 'b', 'c']

# Default values are None:
d = dict.fromkeys(keys)
# {'a': None, 'b': None, 'c': None}

# With a default value:
d = dict.fromkeys(keys, 0)
# {'a': 0, 'b': 0, 'c': 0}

# ⚠️ Mutable default is shared:
d = dict.fromkeys(keys, [])
d['a'].append(1)
# All values become [1]!
dict(zip(keys, values))
Returns NewPattern

The classic idiom for creating a dictionary from two parallel sequences. Stops at the shorter iterable.

keys = ['name', 'age', 'city']
values = ['Alice', 30, 'NYC']

person = dict(zip(keys, values))
# {'name': 'Alice', 'age': 30, 'city': 'NYC'}

# Unequal lengths — zip stops at shortest:
dict(zip(['a', 'b'], [1, 2, 3]))
# {'a': 1, 'b': 2}
dict(**kwargs)
Returns NewBuilt-in

Create a dictionary from keyword arguments. Keys must be valid Python identifiers. Clean and readable for simple cases.

config = dict(
    host='localhost',
    port=8080,
    debug=True
)
# {'host': 'localhost', 'port': 8080, 'debug': True}

# Keys must be valid identifiers:
# dict(1='one')  # SyntaxError!
# Use {'1': 'one'} instead
🔑
Accessing Values
4 items
d[key]
OperatorReturns Value

Bracket notation for dictionary lookup. Raises KeyError if key is not found. Fastest lookup method.

person = {'name': 'Alice', 'age': 30}

name = person['name']
# 'Alice'

# Raises KeyError if missing:
# person['city']  # KeyError: 'city'

# Safe check first:
if 'city' in person:
    city = person['city']
d.get(key, default)
Returns Value

Return the value for key if it exists, else return default (None if not specified). Never raises KeyError.

person = {'name': 'Alice'}

age = person.get('age')
# None (default default)

age = person.get('age', 0)
# 0

city = person.get('city', 'Unknown')
# 'Unknown'

# Perfect for nested access:
data.get('user', {}).get('name')
d.setdefault(key, default)
MutatesReturns Value

If key exists, return its value. If not, insert key with default value and return default. One-line get-or-create.

counts = {}

# If 'apple' not in counts, set to 0, then return it:
counts.setdefault('apple', 0)
# 0, and counts is now {'apple': 0}

counts['apple'] += 1
# counts → {'apple': 1}

# Grouping pattern:
groups = {}
for item in items:
    key = item.category
    groups.setdefault(key, []).append(item)
collections.defaultdict
Returns NewModule

A dictionary subclass that calls a factory function to supply missing values. Eliminates manual key initialization.

from collections import defaultdict

# Default value is 0:
counts = defaultdict(int)
counts['apple'] += 1
# counts → {'apple': 1} (no KeyError!)

# Default value is empty list:
groups = defaultdict(list)
groups['fruits'].append('apple')

# Custom factory:
def default_user():
    return {'name': '', 'active': False}
users = defaultdict(default_user)
Adding & Updating
3 items
d[key] = value
MutatesOperator

Set a key to a value. If key exists, overwrites. If not, creates new entry. The fundamental dictionary assignment.

person = {'name': 'Alice'}

# Add new key:
person['age'] = 30
# {'name': 'Alice', 'age': 30}

# Update existing key:
person['age'] = 31
# {'name': 'Alice', 'age': 31}

# Dynamic key:
key = 'city'
person[key] = 'NYC'
d.update(other)
Mutates

Update dictionary with key-value pairs from other. Overwrites existing keys. Accepts dicts, iterables, and keyword args.

person = {'name': 'Alice', 'age': 30}

# Update from another dict:
person.update({'age': 31, 'city': 'NYC'})
# {'name': 'Alice', 'age': 31, 'city': 'NYC'}

# Update from keyword args:
person.update(country='USA', job='Engineer')

# Update from iterable of pairs:
person.update([('hobby', 'coding')])
d |= other
MutatesOperator

In-place union operator (Python 3.9+). Equivalent to update() but can be used in expressions. Updates left dict in-place.

person = {'name': 'Alice'}
defaults = {'age': 0, 'city': 'Unknown'}

# In-place merge:
person |= defaults
# person → {'name': 'Alice', 'age': 0, 'city': 'Unknown'}

# Can chain (unlike update):
person |= {'country': 'USA'}

# Works in expressions:
result = (person := person | {'active': True})
🗑
Removing Elements
4 items
del d[key]
MutatesStatement

Delete a key-value pair. Raises KeyError if key doesn't exist. No return value. Use for unconditional deletion.

person = {'name': 'Alice', 'age': 30, 'city': 'NYC'}

del person['age']
# {'name': 'Alice', 'city': 'NYC'}

# Safe deletion:
if 'age' in person:
    del person['age']

# del is a statement, not expression:
# x = del person['age']  # SyntaxError!
d.pop(key, default)
MutatesReturns Value

Remove key and return its value. If key is missing and default provided, return default. Otherwise raises KeyError.

person = {'name': 'Alice', 'age': 30}

age = person.pop('age')
# age = 30, person → {'name': 'Alice'}

# With default:
city = person.pop('city', 'Unknown')
# city = 'Unknown', no error

# Remove and process:
while person:
    key, value = person.popitem()
    print(f"{key}: {value}")
d.popitem()
MutatesReturns Tuple

Remove and return the last inserted (key, value) pair as a tuple. LIFO order in Python 3.7+. Raises KeyError if empty.

person = {'a': 1, 'b': 2, 'c': 3}

item = person.popitem()
# item → ('c', 3)  (LIFO in 3.7+)
# person → {'a': 1, 'b': 2}

# Safe emptying:
while person:
    key, value = person.popitem()
    print(f"Processing {key}={value}")

# Before 3.7, order was arbitrary
d.clear()
Mutates

Remove all items from the dictionary. Keeps the same object identity. Useful for resetting state.

cache = {'a': 1, 'b': 2}

id_before = id(cache)
cache.clear()
# cache → {}
id(cache) == id_before   # True (same object)

# Equivalent but less explicit:
cache = {}   # Creates NEW dict object

# Use clear() when other variables reference the dict
🔍
Querying & Inspecting
7 items
len(d)
Returns IntBuilt-in

Return the number of key-value pairs. O(1) operation. Works on all built-in collections.

person = {'name': 'Alice', 'age': 30}

len(person)    # 2
len({})        # 0

# Truthiness:
if person:     # True if len > 0
if not person: # True if empty
key in d
Returns BoolOperator

Test if a key exists in the dictionary. O(1) average case. Uses hash lookup. The Pythonic way to check membership.

person = {'name': 'Alice', 'age': 30}

'name' in person      # True
'salary' in person    # False

# Negation:
'city' not in person  # True

# Note: checks keys, not values:
'Alice' in person     # False (it's a value)
d.keys()
Returns View

Return a view object of all keys. Dynamic — reflects dict changes. Iterable and supports membership testing.

person = {'name': 'Alice', 'age': 30}

keys = person.keys()
# dict_keys(['name', 'age'])

# Membership test (O(1)):
'name' in keys   # True

# Convert to list if needed:
list(keys)   # ['name', 'age']

# Dynamic view:
person['city'] = 'NYC'
# keys now includes 'city'
d.values()
Returns View

Return a view object of all values. Dynamic — reflects dict changes. Membership test is O(n) since values aren't hashed.

person = {'name': 'Alice', 'age': 30}

values = person.values()
# dict_values(['Alice', 30])

# Membership is O(n):
'Alice' in values   # True

# Convert to list:
list(values)   # ['Alice', 30]

# Dynamic:
person['city'] = 'NYC'
# values now includes 'NYC'
d.items()
Returns View

Return a view of (key, value) tuples. The standard way to iterate over both keys and values simultaneously.

person = {'name': 'Alice', 'age': 30}

items = person.items()
# dict_items([('name', 'Alice'), ('age', 30)])

# Iterate:
for key, value in person.items():
    print(f"{key}: {value}")

# Convert to list of tuples:
list(person.items())
# [('name', 'Alice'), ('age', 30)]
d.copy()
Returns New

Return a shallow copy of the dictionary. New dict object with same key-value references. Fast and Pythonic.

original = {'a': 1, 'b': [2, 3]}
copied = original.copy()

# Different objects:
copied is original     # False
copied == original       # True

# But nested objects are shared:
copied['b'].append(4)
# original['b'] → [2, 3, 4]

# Equivalent: dict(original), original[:]
d == other
Returns BoolOperator

Compare two dictionaries for equality. True if same key-value pairs regardless of insertion order (in 3.7+ order also matches).

a = {'x': 1, 'y': 2}
b = {'y': 2, 'x': 1}

a == b   # True (same pairs)
a is b   # False (different objects)

# Nested dicts compared recursively:
c = {'a': {'b': 1}}
d = {'a': {'b': 1}}
c == d   # True
🔀
Merging & Copying
5 items
d1 | d2
Returns NewOperator

Union operator (Python 3.9+). Returns a new dictionary with keys from both. Right side wins on conflicts. Originals unchanged.

defaults = {'theme': 'dark', 'font': '16px'}
user = {'font': '14px', 'lang': 'en'}

merged = defaults | user
# {'theme': 'dark', 'font': '14px', 'lang': 'en'}
# defaults and user unchanged

# Can chain:
result = a | b | c | {'extra': True}
d1 |= d2
MutatesOperator

In-place union operator (Python 3.9+). Updates d1 with keys from d2. Right side wins conflicts. Returns None.

config = {'host': 'localhost', 'port': 8080}
overrides = {'port': 3000, 'debug': True}

config |= overrides
# config → {'host': 'localhost', 'port': 3000, 'debug': True}

# Equivalent to update() but operator syntax:
# config.update(overrides)
{**d1, **d2}
Returns NewPattern

Dictionary unpacking (Python 3.5+). Unpacks key-value pairs into a new dict. Rightmost values win on conflicts.

base = {'a': 1, 'b': 2}
extra = {'b': 3, 'c': 4}

merged = {**base, **extra}
# {'a': 1, 'b': 3, 'c': 4}

# Add extra keys inline:
result = {**base, 'd': 5, **extra}

# Merge multiple dicts:
all_three = {**a, **b, **c}
copy.deepcopy()
Returns NewModule

Create a deep copy — recursively copies all nested objects. No shared references. Use for nested mutable structures.

import copy

data = {
    'users': [{'name': 'Alice'}],
    'settings': {'theme': 'dark'}
}

copied = copy.deepcopy(data)
copied['users'][0]['name'] = 'Bob'

# copied['users'][0]['name'] → 'Bob'
# data['users'][0]['name'] → 'Alice' (unaffected!)
collections.ChainMap
Returns NewModule

Group multiple dicts into a single view without copying. Lookups search left-to-right. Mutations affect the first dict.

from collections import ChainMap

defaults = {'theme': 'dark', 'lang': 'en'}
user = {'lang': 'fr'}

config = ChainMap(user, defaults)
config['lang']    # 'fr' (from user)
config['theme']   # 'dark' (from defaults)

# No copying — memory efficient:
len(config)   # 2 (only user keys count)
🔄
Iteration & Views
4 items
for k in d
Pattern

Iterate over dictionary keys. In Python 3.7+, keys are yielded in insertion order. The most common iteration pattern.

person = {'name': 'Alice', 'age': 30, 'city': 'NYC'}

for key in person:
    print(key)
# name, age, city (insertion order)

# Equivalent to:
for key in person.keys():
    print(key)
for k, v in d.items()
Pattern

Iterate over key-value pairs simultaneously. The standard Pythonic pattern for accessing both during iteration.

scores = {'Alice': 95, 'Bob': 87, 'Carol': 92}

for name, score in scores.items():
    print(f"{name}: {score}")

# Build a new dict from items:
capped = {k: min(v, 90) for k, v in scores.items()}
View Objects
Dynamic ViewPattern

keys(), values(), and items() return dynamic views. They reflect dict changes in real-time and support set-like operations.

d = {'a': 1, 'b': 2, 'c': 3}
keys = d.keys()

# Dynamic — reflects changes:
d['d'] = 4
len(keys)   # 4

# Set operations on keys:
d1 = {'a': 1, 'b': 2}
d2 = {'b': 3, 'c': 4}
d1.keys() & d2.keys()   # {'b'} (intersection)
d1.keys() | d2.keys()   # {'a', 'b', 'c'} (union)
iter(d) / reversed(d)
IteratorBuilt-in

iter(d) returns an iterator over keys. reversed(d) yields keys in reverse insertion order (Python 3.8+).

d = {'a': 1, 'b': 2, 'c': 3}

# Iterator over keys:
it = iter(d)
next(it)   # 'a'
next(it)   # 'b'

# Reverse iteration (3.8+):
for key in reversed(d):
    print(key)
# c, b, a

# Convert to list:
list(reversed(d))   # ['c', 'b', 'a']
Dictionary Comprehensions
5 items
{k: v for k, v in ...}
Returns NewPattern

Basic dictionary comprehension. Transform iterables into dictionaries. Faster and more readable than loops.

# Squares mapping:
{k: k**2 for k in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# From two lists:
keys = ['a', 'b', 'c']
values = [1, 2, 3]
{k: v for k, v in zip(keys, values)}
# {'a': 1, 'b': 2, 'c': 3}
{k: v for ... if cond}
Returns NewPattern

Filtered dictionary comprehension. Only include items where the condition is True. Powerful one-line filtering.

scores = {'Alice': 95, 'Bob': 72, 'Carol': 88, 'Dave': 91}

# Only passing scores:
{k: v for k, v in scores.items() if v >= 80}
# {'Alice': 95, 'Carol': 88, 'Dave': 91}

# Filter by key:
{k: v for k, v in scores.items() if k.startswith('A')}
{k: v if cond else alt for ...}
Returns NewPattern

Conditional expression inside comprehension. Transform values based on conditions while keeping all keys.

scores = {'Alice': 95, 'Bob': 72, 'Carol': 88}

# Pass/fail labels:
{k: ('pass' if v >= 80 else 'fail') for k, v in scores.items()}
# {'Alice': 'pass', 'Bob': 'fail', 'Carol': 'pass'}

# Clamp values:
{k: (min(v, 100) if v > 0 else 0) for k, v in scores.items()}
Nested comprehensions
Returns NewPattern

Nested loops inside comprehensions for flattening or building multi-level structures. Readability decreases with depth.

# Flatten nested data:
data = {'a': [1, 2], 'b': [3, 4]}
{k: v for k, lst in data.items() for v in lst}
# Not valid — duplicate keys!

# Group by first letter:
words = ['apple', 'apricot', 'banana', 'cherry']
{w[0]: [x for x in words if x.startswith(w[0])] for w in words}
# {'a': ['apple', 'apricot'], 'b': ['banana'], 'c': ['cherry']}
dict() with zip/enumerate
Returns NewPattern

Use dict() constructor with zip() or enumerate() for clean one-liners when creating dicts from sequences.

keys = ['a', 'b', 'c']
values = [1, 2, 3]

# Classic idiom:
dict(zip(keys, values))
# {'a': 1, 'b': 2, 'c': 3}

# Enumerate for index mapping:
dict(enumerate(['x', 'y', 'z']))
# {0: 'x', 1: 'y', 2: 'z'}

# With start:
dict(enumerate(['a', 'b'], start=1))
# {1: 'a', 2: 'b'}
🧩
Common Patterns & Tricks
7 items
Grouping with setdefault
PatternMutates

Group items by a key without imports. setdefault creates the list on first access, then appends each item.

words = ['apple', 'apricot', 'banana', 'blueberry', 'cherry']

groups = {}
for word in words:
    first = word[0]
    groups.setdefault(first, []).append(word)

# {'a': ['apple', 'apricot'],
#  'b': ['banana', 'blueberry'],
#  'c': ['cherry']}

# Equivalent with defaultdict:
from collections import defaultdict
groups = defaultdict(list)
for word in words:
    groups[word[0]].append(word)
Inverting a dictionary
PatternReturns New

Swap keys and values. Values must be unique and hashable. For non-unique values, group into lists.

original = {'a': 1, 'b': 2, 'c': 3}

# Simple inversion (values unique):
inverted = {v: k for k, v in original.items()}
# {1: 'a', 2: 'b', 3: 'c'}

# Handle duplicate values:
original = {'a': 1, 'b': 1, 'c': 2}
inverted = {}
for k, v in original.items():
    inverted.setdefault(v, []).append(k)
# {1: ['a', 'b'], 2: ['c']}
collections.Counter
ModuleReturns New

A specialized dict for counting hashable objects. Returns 0 for missing keys instead of KeyError. Powerful frequency analysis.

from collections import Counter

words = ['apple', 'banana', 'apple', 'cherry', 'apple']
counts = Counter(words)
# Counter({'apple': 3, 'banana': 1, 'cherry': 1})

counts['apple']     # 3
counts['grape']    # 0 (no error!)

# Most common:
counts.most_common(2)
# [('apple', 3), ('banana', 1)]
Frequency count (manual)
PatternMutates

Manual frequency counting without imports. Useful when Counter is overkill or you need custom logic.

items = ['a', 'b', 'a', 'c', 'a', 'b']

# Using get():
counts = {}
for item in items:
    counts[item] = counts.get(item, 0) + 1
# {'a': 3, 'b': 2, 'c': 1}

# Using setdefault:
counts = {}
for item in items:
    counts.setdefault(item, 0)
    counts[item] += 1
Merge with lambda / logic
PatternReturns New

Merge dictionaries with custom conflict resolution using a loop or collections.Counter for numeric values.

d1 = {'a': 10, 'b': 20}
d2 = {'b': 30, 'c': 40}

# Sum values on conflict:
merged = {k: d1.get(k, 0) + d2.get(k, 0) for k in d1.keys() | d2.keys()}
# {'a': 10, 'b': 50, 'c': 40}

# Max on conflict:
merged = {k: max(d1.get(k, 0), d2.get(k, 0)) for k in d1.keys() | d2.keys()}
max(d, key=d.get)
PatternBuilt-in

Find the key with the maximum value. d.get is passed as the key function. Elegant one-liner for rankings.

scores = {'Alice': 95, 'Bob': 87, 'Carol': 92}

# Key with max value:
max(scores, key=scores.get)
# 'Alice'

# Key with min value:
min(scores, key=scores.get)
# 'Bob'

# Get the actual max value:
max(scores.values())
# 95
Sort dict by value
PatternReturns New

Sort a dictionary by its values (or keys) and return a new dict. Python 3.7+ preserves insertion order.

scores = {'Alice': 95, 'Bob': 87, 'Carol': 92}

# Sort by value ascending:
dict(sorted(scores.items(), key=lambda x: x[1]))
# {'Bob': 87, 'Carol': 92, 'Alice': 95}

# Sort by value descending:
dict(sorted(scores.items(), key=lambda x: x[1], reverse=True))

# Sort by key:
dict(sorted(scores.items()))

d[key] vs d.get() vs d.setdefault()

Choosing the right access method prevents KeyErrors and keeps your code clean.

Featured[key]d.get(key, default)d.setdefault(key, default)
Returns on missRaises KeyErrordefault (or None)default (and inserts it)
Mutates dictNoNoYes (if key missing)
Default valueN/AConfigurableConfigurable
Raises errorYesNoNo
Use caseYou know key existsSafe read with fallbackGet-or-create pattern

update() vs | vs |= vs {**a, **b}

Python offers multiple ways to merge dictionaries. Choose based on whether you need a new dict or in-place mutation.

Featured.update(other)d1 | d2d1 |= d2{**a, **b}
ReturnsNoneNew dictNoneNew dict
Mutates aYesNoYesNo
Mutates bNoNoNoNo
Works onAny mappingDicts onlyDicts onlyAny mapping
Python versionAll3.9+3.9+3.5+

pop() vs del vs popitem()

Three ways to remove items. Choose based on whether you need the value back, a default fallback, or LIFO removal.

Featured.pop(key, default)del d[key]d.popitem()
ReturnsValue (or default)Nothing(key, value) tuple
Default on missYes (if provided)No (raises KeyError)No (raises KeyError)
RaisesKeyError (no default)KeyErrorKeyError (if empty)
OrderSpecific keySpecific keyLIFO (last inserted, 3.7+)

Time Complexity Reference

Big-O complexity for common dictionary operations. Assumes average case with good hash distribution.

OperationAverage CaseWorst CaseNotes
Get d[key]O(1)O(n)Hash collision chain
Set d[key] = valO(1)O(n)May trigger resize
Delete del d[key]O(1)O(n)Hash collision chain
Iteration (keys/values/items)O(n)O(n)Over all n items
d.keys() / d.values()O(1)O(1)Returns view, not copy
d.items()O(1)O(1)Returns view, not copy
len(d)O(1)O(1)Stored internally
key in dO(1)O(n)Hash lookup
Merge (| or update)O(m)O(m*n)m = size of other dict
d.copy()O(n)O(n)Shallow copy

n = number of items in dictionary. Worst case occurs with malicious hash collisions or extremely poor hash distribution.

Pro Tips & Gotchas

Common pitfalls and powerful techniques every Python developer should know when working with dictionaries.

⚠ Mutable Default Arguments with Dicts

Never use {} as a default argument. It creates one dict at function definition time, shared across all calls. Use None instead and assign d = d or {} inside.

🔄 Modifying While Iterating

Never add or delete keys while iterating over a dict. It raises RuntimeError. Instead, iterate over list(d.items()) or build a new dict with a comprehension.

🔑 Keys Must Be Hashable

Dictionary keys must be hashable (immutable): strings, numbers, tuples of hashables. Lists and dicts cannot be keys. Use tuple(my_list) if you need a list as a key.

👁 View Objects Are Dynamic

keys(), values(), and items() return live views. They reflect dict changes in real-time. If you need a static snapshot, convert to list().

🏠 Using get() for Nested Dicts

Chain .get() with defaults for safe nested access: data.get('user', {}).get('profile', {}).get('name'). Returns None at any missing level without errors.

🔢 Counter vs Manual Frequency

Use collections.Counter for counting — it's optimized, readable, and handles edge cases. For simple cases without imports, counts[x] = counts.get(x, 0) + 1 is fine.

System Online — 50+ Methods Loaded
Python Dictionary Methods Cheat Sheet v1.0 | DevToolkit