Why del has to be a Python builtin

A posting today to the LiveJournal python_dev community wound up sort of asking why del has to be a Python builtin instead of a method. At first I thought this had a nice simple answer, but the more I thought about it the less obvious it became, and by the time I'd worked out a satisfying answer I'd had to really think about how Python fits together.

The short summary is that del needs to be a builtin because Python's object model is based on references and namespaces, and Python doesn't have a way to refer to your current namespaces (they have no explicit name).

Unlike in some languages, del does not literally delete objects; instead it removes references to them (which may as a side effect delete the object). In other words, del is not an object manipulation operation, it is a namespace manipulation operation. So the correct translation of ' del d ' to a method call version cannot be ' d.delete() '; it has to be ' namespace .delete("d") '. But Python provides no magic namespace name for you to use for this operation, because del finds it implicitly. (Compound cases give the namespace; ' del d.c ' is explicitly operating on d 's namespace and duly translates to d.__delattr__("c") .)

There are at least three such anonymous Python namespaces: globals, function locals (including closures), and the namespace of a class as it is being built. Of these, only the global namespace is really accessible; the latter two can only be gotten with magic, and even then you can't use __delattr__ on them. del itself does internal interpreter magic to make it all go.

(Note that locals() is explicitly not a reference to the function's namespace; it is a dictionary copy of the function's current namespace. This is because functions don't implement their namespaces using Python dictionaries. Even for things that do implement their namespace using a Python dict , it's best considered an implementation detail.)

Sidebar: all but deleting yourself

While an object cannot literally delete itself in Python, it can try real hard, by scrubbing its __dict__ and changing its __class__ to something that does nothing. (Unfortunately you can't set your __class__ to plain object , as far as I can tell; you'll need to make an actual do-nothing class.)