dict.popitem()

Since 3.7 it is strictly last-in-first-out, which turned an old "arbitrary item" method into a usable stack pop.

Dict methodPython 1.0+Live demo
Common call
key, value = d.popitem()
Returns
tuple — the most recently inserted pair
Replaces
next(reversed(d)) followed by del
Watch out
KeyError on an empty dict — there is no default argument to soften it
dict.popitem()
tuple

Demo

Live evaluation
Try:
Inputs
dictdictkey:value pairs, comma separated
Output
{'a': '1', 'b': '2'}.popitem()
('b', '2')

popitem takes the pair that was inserted most recently and removes it, returning it as a (key, value) tuple. With {"a": 1, "b": 2} that is ("b", 2). Because dicts have kept insertion order since 3.7, this is genuinely LIFO and repeated calls walk backwards through the dict. On an empty dict it raises KeyError, and unlike dict.pop there is no default argument to return instead.

Common patterns

Drain a dict completely
Each call removes one pair, so the loop ends when the dict is empty.
while d:
    key, value = d.popitem()
    handle(key, value)
Use a dict as an ordered stack
Insertion order plus LIFO removal gives stack behaviour with key lookup.
pending[task_id] = payload
...
task_id, payload = pending.popitem()
Take the most recent entry
Reads clearly when the newest item is the one you want.
latest_key, latest_value = cache.popitem()

Examples

1. Last pair
{'a': 1, 'b': 2}.popitem()
Returns
('b', 2)
2. Single pair
{'only': 1}.popitem()
Returns
('only', 1)
3. Empty raises
{}.popitem()
Returns
KeyError: 'popitem(): dictionary is empty'
4. It mutates
d = {'a': 1, 'b': 2} d.popitem() d
Returns
{'a': 1}
5. Walks backwards
d = {'a': 1, 'b': 2} d.popitem(), d.popitem()
Returns
(('b', 2), ('a', 1))
6. Unpacks directly
k, v = {'a': 1}.popitem() k
Returns
'a'

Pitfalls

1. KeyError on an empty dict, with no default
dict.pop lets you pass a fallback; popitem does not. Draining a dict without checking it is non-empty is the usual way this bites.
Unguarded
d = {}
d.popitem()
KeyError: 'popitem(): dictionary is empty'
Guard the loop
while d:
    k, v = d.popitem()
stops cleanly
2. LIFO order is only guaranteed from 3.7
Before 3.7 the docs described the item as arbitrary, and it genuinely varied. Code that relies on getting the newest pair is correct on modern Python and silently wrong on old interpreters.
Pre-3.7 assumption
d.popitem()   # "the last one"
arbitrary pair on 3.6 and earlier
Be explicit
k = next(reversed(d))
v = d.pop(k)
newest pair, stated plainly
3. Confused with dict.pop
pop takes a key and returns the VALUE; popitem takes nothing and returns a PAIR. Swapping them produces a TypeError or a tuple where a value was expected.
Wrong shape
value = {'a': 1}.popitem()
('a', 1) # a tuple, not 1
Unpack it
key, value = {'a': 1}.popitem()
value is 1
4. Calling it while iterating
Removing entries during a for loop over the dict raises RuntimeError, because the dict changed size mid-iteration. Drain with a while loop instead.
Mutating mid-loop
for k in d:
    d.popitem()
RuntimeError: dictionary changed size during iteration
while instead
while d:
    d.popitem()
drains safely

When to use

Use it
  • Draining a dict pair by pair
  • Treating a dict as a LIFO stack that also supports key lookup
  • Taking the most recently added entry
Reach for something else
  • Removing a SPECIFIC key → dict.pop(key)
  • Reading without removing → the newest key via next(reversed(d))
  • Supporting Python 3.6 or older where the order is arbitrary

Notes

Complexity
O(1) amortised — removes from the end of the insertion order
Return
A new two-item tuple; the pair is gone from the dict afterwards
CPython impl
Objects/dictobject.c :: dict_popitem_impl
Memory
Allocates one small tuple; may shrink the dict internally
Thread-safe
Not safe under concurrent mutation of the same dict

FAQ

Since Python 3.7 it is always the most recently inserted pair, because dicts preserve insertion order. Before 3.7 the language only promised "an arbitrary item", and in practice it was the first in internal hash order.

d = {'a': 1, 'b': 2}
d.popitem()   # ('b', 2)

History

1.0
popitem present since early Python, documented as returning an arbitrary pair.
3.7
Insertion order became a language guarantee, making popitem reliably LIFO.