Back to Blog
Python

Python dict pop: Syntax, Defaults, and Pitfalls

python dict pop: Learn how to use Python's dict.pop() method to remove keys and retrieve values, including default handling and common pitfalls.

Pythondictionarypopkey removaldefault value
Illustration of a Python dictionary with a key being removed and its value retrieved using the pop method.

python dict pop requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

The dict.pop() method in Python removes a key from a dictionary and returns its value. It is one of the most direct ways to delete a key while capturing the associated data in a single operation. The method accepts two arguments: the key to remove and an optional default value to return if the key is not present.

The Syntax of dict.pop

The signature of pop() is dict.pop(key[, default]). When you call it with only a key, the method removes that key from the dictionary and returns the corresponding value. If the key is missing, a KeyError is raised. The optional default argument changes that behavior: if the key is absent, pop() returns the default value instead of raising an exception, and the dictionary remains unchanged.

inventory = {"apples": 5, "bananas": 3} apples = inventory.pop("apples") print(apples) # 5 print(inventory) # {"bananas": 3}

This simple example shows the core behavior. The key "apples" is removed, and its value is assigned to the variable. The dictionary now contains only the remaining items. The method is often used when you need to consume an entry from a dictionary, such as when processing a queue of tasks or extracting configuration values that should not remain in the source dictionary.

Using the Default Argument to Avoid KeyError

The most common practical use of pop() involves the default parameter. Without it, a missing key raises an exception, which may be acceptable in some cases but often forces you to handle the error explicitly. With a default, you can write code that does not need a try-except block for the common case where the key might not exist.

settings = {"theme": "dark", "language": "en"} font_size = settings.pop("font_size", 14) print(font_size) # 14 print(settings) # {"theme": "dark", "language": "en"}

Here, "font_size" is not a key in the dictionary, so pop() returns the default 14 and leaves the dictionary unchanged. This pattern is useful when you want to extract an optional setting and apply a fallback value. It also works well when you need to remove a key only if it exists, without raising an error.

Popping Keys While Iterating: A Common Pitfall

A frequent mistake is calling pop() on a dictionary while iterating over it. In Python, changing the size of a dictionary during iteration raises a RuntimeError. This happens because the iterator holds a reference to the dictionary's internal state, and any modification that changes the number of keys invalidates that state.

data = {"a": 1, "b": 2, "c": 3} for key in data: if key == "b": data.pop(key) # RuntimeError: dictionary changed size during iteration

To avoid this, you can iterate over a copy of the keys, or collect the keys to remove first and then pop them after the loop. The latter approach is often cleaner because it separates the decision from the mutation.

data = {"a": 1, "b": 2, "c": 3} keys_to_remove = [key for key in data if key == "b"] for key in keys_to_remove: data.pop(key) print(data) # {"a": 1, "c": 3}

This pattern is safe because the iteration happens over the list, not the dictionary. It also makes the logic more explicit and easier to test.

When to Use pop Instead of del or get

del dict[key] removes a key but does not return the value. If you need the value, you must first read it with dict[key] and then delete it, which is two operations and can raise a KeyError if the key is missing. pop() combines both steps and gives you control over missing keys via the default argument.

dict.get(key, default) returns the value without removing the key. Use get() when you need to read a value but keep the entry in the dictionary. Use pop() when you want to remove the entry as part of the operation. The choice depends on whether the key should remain in the dictionary after you access it.

The table below summarizes the key differences:

MethodRemoves KeyReturns ValueRaises on Missing KeyDefault Support
dict.pop(key)YesYesYesYes (with second arg)
dict.pop(key, d)YesYesNoYes
del dict[key]YesNoYesNo
dict.get(key, d)NoYesNoYes

In practice, pop() is the right choice when you need to remove an item and use its value immediately, especially when the key might not exist and you have a sensible fallback. It reduces the number of lines and avoids separate existence checks.

Performance and Runtime Behavior of dict.pop

The pop() method has an average time complexity of O(1) because it relies on the hash table lookup. The actual operation involves computing the hash of the key, locating the bucket, and removing the entry. In the worst case, when many keys collide, the complexity can degrade, but that is rare and depends on the hash function and the dictionary's load factor.

Memory-wise, pop() does not immediately shrink the underlying hash table. Python's dictionary implementation may leave the allocated memory in place to avoid the cost of resizing. If you remove many items and the dictionary becomes sparse, the memory is not necessarily released to the operating system. The dict.clear() method is more aggressive if you need to free all entries at once.

For most applications, the performance difference between pop(), del, and get() is negligible. The choice should be based on clarity and the need to capture the value. If you are popping many items in a loop, the overhead is dominated by the hash computation, not the method call itself.

Real-World Patterns: Consuming and Transferring Items

A common pattern is using pop() to transfer items from one dictionary to another. For example, when processing a batch of configuration overrides, you might extract known keys and leave the rest untouched.

config = {"host": "localhost", "port": 8080, "debug": True} host = config.pop("host") port = config.pop("port") # config now contains only "debug"

This is useful when you want to separate required fields from optional ones. Another pattern is using pop() to remove a key after it has been processed, ensuring that the same item is not handled twice. This is common in event-driven systems where messages are stored in a dictionary and each message is removed once consumed.

pending_tasks = {"task_1": "send_email", "task_2": "update_db"} while pending_tasks: task_id, action = pending_tasks.popitem() # note: popitem removes last item # process task

Note that popitem() is a separate method that removes and returns an arbitrary (key, value) pair. It is not the same as pop() with a specific key. Use popitem() when you do not care which item you get, such as when draining a dictionary. For a specific key, pop() is the appropriate tool.

Edge Cases and Compatibility Notes

When using pop(), be aware that the key must be hashable. If you try to pop with an unhashable type, such as a list, Python raises a TypeError. This is the same requirement as any dictionary operation. Also, if the key is present but its value is None, pop() returns None and removes the key, which is correct but can be confusing if you expected a missing key to also return None. The default argument only applies when the key is absent, not when the value is None.

Another edge case is popping from a dictionary that is being viewed through a view object. For example, dict.keys() returns a view that does not support pop(). You must call pop() on the dictionary itself. This is a common mistake when trying to remove keys based on a view.

d = {"x": 1, "y": 2} keys = d.keys() # keys.pop("x") # AttributeError: 'dict_keys' object has no attribute 'pop'

In Python 3.7 and later, dictionary insertion order is guaranteed, but pop() does not rely on that order. It removes the specified key regardless of its position. This is important if you are using dictionaries to maintain an ordered set of items; pop() will not affect the relative order of the remaining keys.

Finally, when you use pop() with a default, the default expression is evaluated even if the key exists. This is a subtle behavior that can have side effects if the default is a function call. For example, d.pop("key", expensive_function()) will call expensive_function() regardless of whether "key" is present. If that function has side effects or is costly, you may want to use a conditional expression instead.

# Avoid this if expensive_function() has side effects value = d.pop("key", expensive_function()) # Safer alternative if "key" in d: value = d.pop("key") else: value = expensive_function()

This nuance is often overlooked but can lead to unexpected behavior in performance-sensitive code. Being aware of it helps you write more predictable dictionary operations.

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