Back to Blog
Python

Using Python dict items() for Key-Value Iteration

python dict items: Learn how Python's dict.items() returns a dynamic view of key-value pairs, how to iterate and unpack it, and when to use it over keys() or values().

pythondictionariesiterationdict-itemspython-syntax
Illustration of a Python dictionary with key-value pairs being iterated through the items() view method

When you call .items() on a Python dictionary, you get a dict_items view object that yields (key, value) tuples as you iterate over it. This is the standard way to access both keys and their associated values together, and it underpins most dictionary iteration in Python. Understanding what python dict items returns, how the view behaves, and where it fits among the other dictionary view methods will make your loops cleaner and your code more predictable.

What the dict_items View Actually Is

The .items() method does not return a list of tuples. It returns a dynamic view object. The view reflects the current state of the dictionary: if you add or remove entries after calling .items(), the view updates to match. This is different from materializing a list with list(d.items()), which captures a snapshot.

d = {"a": 1, "b": 2} view = d.items() print(view) # dict_items([('a', 1), ('b', 2)]) d["c"] = 3 print(view) # dict_items([('a', 1), ('b', 2), ('c', 3)])

The view also supports set-like operations because the tuples it contains are hashable. You can test membership with ("a", 1) in view, and you can compute intersections or differences between two dict_items views. This makes .items() useful beyond simple iteration.

Iterating Over Keys and Values Together

The most common use of .items() is in a for loop where you need both the key and the value. Iterating directly over the dictionary gives you only the keys, and using .keys() or .values() alone loses the pairing.

config = {"host": "localhost", "port": 5432, "timeout": 30} for key, value in config.items(): print(f"{key} = {value}")

The unpacking in the for statement works because each item is a two-element tuple. Python's tuple unpacking assigns the first element to key and the second to value. This is the pattern you will see in most real-world Python code that processes dictionary contents.

Unpacking and Destructuring Items

Beyond the for loop, .items() integrates with other unpacking contexts. You can convert it to a list of tuples, or unpack it directly into variables when the dictionary has a known structure.

pair = {"name": "api-server", "port": 8080} (k, v), = pair.items() print(k, v) # name api-server

The trailing comma in (k, v), = is required because .items() returns an iterable, and unpacking an iterable with one element needs the comma to indicate a single-element tuple on the left-hand side. This pattern is less common but appears when you need to extract the only entry from a dictionary.

Modifying a Dictionary While Iterating

A critical runtime behavior: you cannot change the size of a dictionary while iterating over its .items() view. Adding or removing keys during the loop raises RuntimeError: dictionary changed size during iteration.

d = {"a": 1, "b": 2, "c": 3} for key, value in d.items(): if value == 2: del d[key] # RuntimeError

The error occurs because the view tracks the dictionary's internal version counter. When the structure changes, the iterator detects the mismatch and aborts. This is a deliberate safety mechanism to prevent undefined behavior.

To remove entries while iterating, collect the keys first and delete them afterward, or build a new dictionary.

d = {"a": 1, "b": 2, "c": 3} to_remove = [key for key, value in d.items() if value == 2] for key in to_remove: del d[key]

Updating the value of an existing key during iteration is allowed, because that does not change the dictionary's size. The view will reflect the updated value when you reach that entry.

Performance and Memory Characteristics

The dict_items view is lazy: it does not allocate a new list of tuples when you call .items(). Iteration produces tuples on the fly. For large dictionaries, this avoids the memory cost of materializing every key-value pair at once.

big = {i: i * 2 for i in range(100_000)} view = big.items() # O(1), no large allocation

The tuple allocation per iteration is the main cost. Each (key, value) tuple is a new object, so iterating over a large dictionary creates many short-lived tuples. If you need to iterate repeatedly over the same dictionary, the view itself is cheap to reuse, but each pass still allocates tuples.

Membership testing with ("k", v) in view is O(1) per check because it uses the dictionary's hash lookup. This is faster than scanning a list of tuples when the dictionary is large.

Comparing items(), keys(), and values()

The three dictionary view methods serve different purposes, and choosing the right one matters for both readability and efficiency.

MethodYieldsTypical use
.items()(key, value) tuplesNeed both key and value together
.keys()keys onlyMembership test or key iteration
.values()values onlyAggregating or checking values

Iterating over the dictionary directly, for key in d, is equivalent to iterating over d.keys(). Use .items() whenever the loop body needs the value as well; looking up the value with d[key] inside the loop is slower and repeats the hash lookup.

# Slower: repeated hash lookup for key in d: value = d[key] # Faster and clearer: single lookup via items() for key, value in d.items(): pass

The difference matters in hot loops, though the absolute cost of a dictionary lookup is small. The readability benefit of .items() is usually the stronger argument.

Using dict_items Views in Set Operations

Because the tuples in a dict_items view are hashable, the view supports set operations when compared with another dict_items view. This allows you to find common key-value pairs between two dictionaries without converting to lists.

a = {"x": 1, "y": 2, "z": 3} b = {"y": 2, "z": 9, "w": 4} common = a.items() & b.items() print(common) # {('y', 2)}

The intersection returns a set of tuples, not a dictionary. This is useful for comparing configuration snapshots or detecting which entries are identical across two dictionaries. Note that the result is a plain set, so you lose the dictionary structure.

Ordering Guarantees and Compatibility

Since Python 3.7, dictionaries preserve insertion order, and .items() iterates in that order. This is guaranteed behavior in CPython and is now part of the language specification. Code that relies on insertion order can safely use .items() without additional sorting.

d = {"first": 1, "second": 2, "third": 3} print([k for k, _ in d.items()]) # ['first', 'second', 'third']

If you need sorted iteration, apply sorted() to the view. Sorting by key or value is a common pattern when producing deterministic output.

for key, value in sorted(d.items()): print(key, value) for key, value in sorted(d.items(), key=lambda item: item[1]): print(key, value)

The first loop sorts by key; the second sorts by value using a lambda that extracts the second element of each tuple. This is a standard idiom for ordered dictionary processing.

When Not to Use items()

There are cases where .items() is not the right tool. If you only need keys, iterate the dictionary directly. If you only need values, use .values(). If you need to transform a dictionary into a list of tuples and keep that list stable, materialize it with list(d.items()) rather than holding a live view.

snapshot = list(d.items()) # stable copy, unaffected by later mutations

The view is also not serializable. If you need to pass dictionary contents to json.dumps() or write them to a file, convert the view to a list or use the dictionary itself. The dict_items object has no JSON representation.

For merging or updating dictionaries, the | operator and .update() method accept iterables of key-value pairs, so you can pass a dict_items view directly:

base = {"a": 1} extra = {"b": 2} base.update(extra.items())

This works because .update() accepts any iterable of two-element sequences. The view satisfies that contract, so you can pass it wherever an iterable of pairs is expected.

python dict items: Practical Usage and Code Examples | RYUSLOG DEV