del in Python: removing a name or an item

In Python, del wipes a name, a list item, a dictionary entry or an attribute: it removes a reference, not necessarily the object itself.
6 min read
Believemy logo

Definition

A running program piles up things it no longer needs: a configuration key that has gone stale, a variable that must not be reused further down. Most of the time, ignoring them is enough; sometimes the data really gets in the way, and it has to go.

del is the word Python keeps for that gesture. It is a statement, not a function: it takes no parentheses, returns nothing, and can therefore never sit to the right of an equals sign. That special status has a reason: it acts on the target itself, whereas a function only receives the contents of a variable, never the label pointing at it.

Depending on what follows it, del wipes a name from the current namespace, an item from a list, an entry from a dictionary or an attribute from an object. Here are the two most common uses.

PYTHON
stock = {"apples": 12, "pears": 4}
del stock["pears"]
print(stock)
# {'apples': 12}

numbers = [10, 20, 30, 40]
del numbers[1]
print(numbers)
# [10, 30, 40]

The collection is changed in place: the original object is the one that moved, and nothing comes out of the operation, not even the item that was removed.

That is where del parts ways with pop and remove, two methods attached to one precise type. It belongs to the grammar, like if or return, so it behaves identically on unrelated objects.


Removing a name is not removing the object

Here is the misunderstanding that costs the most: many people read del as an order to destroy, room handed back to memory. That is not what happens.

A variable is not a box holding a value, it is a label stuck on an object. Two labels can point at the same object, which happens as soon as a list is passed to a function. What del peels off is the label.

PYTHON
a = [1, 2, 3]
b = a          # two names, a single object

del a
print(b)       # [1, 2, 3]: the object is still alive

The name a has left the current namespace, and using it again raises a NameError. The object itself is doing fine, since b still points at it.

This statement therefore manages names, not memory. Python counts the references pointing at each object and hands the room back once that counter drops to zero: removing the last reference does free the object, but as a consequence, never as a promise.

Good to know

Not to be confused with __del__, the magic method called at the moment an object is actually destroyed. The del statement only triggers it when it removes the last reference.


What it wipes depending on the target

The same statement covers five forms. What changes from one line to the next is not the effect, which is fairly predictable, but the way it fails: that is the column to read first when the target comes from a file or from the network.

FormEffectIf the target is missing
del nameRemoves the name from the current namespaceNameError
del items[2]Removes the item at position 2IndexError
del items[1:3]Removes a whole sliceNothing, slicing is forgiving
del prices["key"]Removes the key and value pairKeyError
del obj.attributeRemoves the attribute from the instanceAttributeError

The slice row stands out: a slice (slicing) does not ask for one precise position but for whatever sits between two bounds. When that area is empty, there is nothing to remove, so nothing to report.

One limit is missing from the table: the target has to be mutable. On an immutable object, a string or a tuple, removing an item is turned down with a TypeError. Wiping the whole name is still possible, without touching the contents.

Then there is scope: inside a function, wiping a variable defined outside means declaring it global beforehand, failing which Python targets the local variable of the same name and complains that it does not exist.


del, pop, remove and clear

Four tools remove items from a list, and each one answers a different request.

ToolWhat it asks forWhat it hands back
del items[i]A positionNothing
items.pop(i)A positionThe removed item
items.remove(v)A valueNothing, and only the first match goes
items.clear()NothingNothing, the list is emptied in place

The choice rests on what you plan to do with the item. If you still need it, pop hands it over along the way; if you do not, del says precisely that, without letting the next reader believe a value is being collected somewhere.

On a dictionary, pop also accepts a fallback value, often None, returned when the key is missing instead of a KeyError: the forgiving version, for keys whose absence is nothing unusual.


The trap of removing while walking through

This last point sends a lot of people looking for help, and for a precise reason: the program does not crash, it hands back a wrong result. Removing items from a list while walking through it shifts the positions under the feet of the loop. When the item at position 1 disappears, the old position 2 slides into position 1, but the loop asks for position 2, and the item that just slid is never examined.

PYTHON
numbers = [1, 2, 2, 3]

# Wrong: the list changes during the walk
for i, n in enumerate(numbers):
    if n == 2:
        del numbers[i]
# [1, 2, 3]: one 2 survived

# Right: rebuild rather than remove
numbers = [n for n in numbers if n != 2]

One 2 survived and nothing flagged it. On four items the oddity shows up; on ten thousand lines it ships to production and only surfaces the day a total refuses to add up.

Warning

Never change a list while you are walking through it. Build the list you want with a list comprehension instead, as in the second half of the example: the result is correct and reads back without effort.

Dictionaries are blunter: changing their size mid-iteration raises an exception straight away instead of skipping entries in silence. Rebuilding stays easier to read anyway than a backwards walk, the other classic answer.


Frequently asked questions

Question

Does del free memory?

Not directly. It removes one reference, and the room is only handed back once the last one disappears. On an object stored inside another list, the memory stays occupied as before and the object remains reachable through its other name.

Question

Can several things be removed on one line?

Yes, by separating the targets with commas: del a, b, stock["pears"] wipes all three. They are handled from left to right, and that is where care is needed. If the second one fails, the first is already gone and the third will never be reached.

Question

Should variables be wiped at the end of a routine?

Rarely. Local variables go away by themselves when the function returns, and systematic use makes the code heavier to read. Two cases justify it: a very large object that should stop being held during a long run, and a reused name whose accidental re-reading must be ruled out.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.