dict.items()

Iterate a dict as (key, value) pairs — a view, not a copy. Insertion order is preserved (3.7+).

Dict methodPython 2.2+Live demo
Common call
for k, v in d.items():
Returns
a dict_items view — live, not a list
Replaces
the manual `for k in d: v = d[k]` pattern
Watch out
mutating d during iteration raises RuntimeError
dict.items()
dict_items

Demo

Live evaluation
Try:
Inputs
dictdictkey: value pairs
Output
{'a': '1', 'b': '2', 'c': '3'}.items()
[['a', '1'], ['b', '2'], ['c', '3']]

The demo materializes the view as a list of pairs so you can see them all at once. In real code you iterate directly: `for k, v in d.items():`. Since Python 3.7 the pair order matches insertion order — earlier versions gave no order guarantee.

Common patterns

Iterate with unpacking
The canonical way to walk a dict when you need both key and value.
for key, value in config.items():
    print(f"{key}={value}")
Invert a dict
One comprehension swaps keys and values — assuming values are hashable and unique.
inverse = {v: k for k, v in original.items()}
Filter to a new dict
Keep only pairs matching a predicate — no manual loop.
kept = {k: v for k, v in d.items() if v is not None}
Sort a dict by value
items() feeds sorted, which returns a list of pairs — rebuild a dict from that.
ordered = dict(sorted(d.items(), key=lambda kv: kv[1]))

Examples

1. Iterate pairs
list({"a": 1, "b": 2}.items())
Returns
[("a", 1), ("b", 2)]
2. Empty is empty
list({}.items())
Returns
[]
3. Insertion order
list({"z": 1, "a": 2}.items())
Returns
[("z", 1), ("a", 2)]
4. View reflects updates
d = {"a": 1} v = d.items() d["b"] = 2 list(v)
Returns
[("a", 1), ("b", 2)]

Pitfalls

1. It is a VIEW, not a list
items() returns a live view. Type checks that expect list, or indexing, both fail. Wrap in list() when you need a snapshot or index access.
Not indexable
d = {"a": 1, "b": 2}
d.items()[0]
TypeError: 'dict_items' object is not subscriptable
Materialize
list(d.items())[0]
('a', 1)
2. Modifying the dict during iteration raises
Changing the dict's size while iterating over its items view is a RuntimeError. Read-only iteration is safe; add/remove keys — take a snapshot first.
Runtime error
for k, v in d.items():
    if v is None:
        del d[k]
RuntimeError: dictionary changed size during iteration
Snapshot first
for k, v in list(d.items()):
    if v is None:
        del d[k]
safe
3. The view lives with the dict
Keeping a reference to items() does not freeze the dict. Later mutations show up when you iterate the same view again — surprising if you thought you had a snapshot.
Not a snapshot
v = d.items()
d["new"] = 99
list(v)  # includes ("new", 99)
view sees the added pair
Snapshot with list
snap = list(d.items())
d["new"] = 99
snap  # unchanged
independent copy

When to use

Use it
  • Iterating with both key and value
  • Comprehensions over dict entries
  • Set-like operations across two dicts (items views are set-like)
  • Feeding sorted / filter / map over pairs
Reach for something else
  • Just the keys → for k in d or d.keys()
  • Just the values → d.values()
  • Index access → list(d.items())
  • Freezing a snapshot for concurrent mutation → list(d.items())

Notes

Complexity
O(1) to create the view; O(n) to iterate
Return
dict_items view — live, sized, iterable, set-like
CPython impl
Objects/dictobject.c :: dictitems_new — no data copied
Memory
O(1) — the view is a small wrapper over the dict
Thread-safe
Iteration is not safe under concurrent mutation of the source dict

FAQ

All three return live views over the same dict. items() gives (key, value) tuples, keys() gives just keys, values() gives just values. Iterating a dict directly (`for k in d`) is equivalent to iterating its keys().

History

2.2
items() introduced (originally as a list-building method).
3.0
items() became a view instead of a list; iteritems() was removed.
3.7
Insertion order preserved by dict — items() iterates in that order.