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.)
|
|