Using __delitem__ with a class object rather than an instance in Python
When you write del obj[key]
, Python calls the __delitem__
method of the class of obj
, not of obj
. So del obj[key]
results in type(obj).__delitem__(obj, key)
.
In your case, that means type(Foo).__delitem__(Foo, 'abcd')
. type(Foo)
is type
, and type.__delitem__
is not defined. You can't modify type
itself, you'll need to change the type of Foo
itself to something that does.
You do that by defining a new metaclass, which is simply a subclass of type
, then instructing Python to use your new metaclass to create the Foo
class (not instances of Foo
, but Foo
itself).
class ClassMapping(type):
def __new__(cls, name, bases, dct):
t = type.__new__(cls, name, bases, dct)
t._instances = {}
return t
def __delitem__(cls, my_str):
del cls._instances[my_str]
class Foo(object):
__metaclass__ = ClassMapping
def __init__(self, my_str):
n = len(Foo._instances) + 1
Foo._instances[my_str] = n
print "Now up to {} instances".format(n)
Changing the metaclass of Foo
from type
to ClassMapping
provides Foo
with
- a class variable
_instances
that refers to a dictionary - a
__delitem__
method that removes arguments from_instances
.
kuzzooroo
Updated on June 05, 2022Comments
-
kuzzooroo almost 2 years
I'd like to be able to use
__delitem__
with a class-level variable. My use case can be found here (the answer that uses_reg_funcs
) but it basically involves a decorator class keeping a list of all the functions it has decorated. Is there a way I can get the class object to support__delitem__
? I know I could keep an instance around specially for this purpose but I'd rather not have to do that.class Foo(object): _instances = {} def __init__(self, my_str): n = len(self._instances) + 1 self._instances[my_str] = n print "Now up to {} instances".format(n) @classmethod def __delitem__(cls, my_str): del cls._instances[my_str] abcd = Foo('abcd') defg = Foo('defg') print "Deleting via instance..." del abcd['abcd'] print "Done!\n" print "Deleting via class object..." del Foo['defg'] print "You'll never get here because of a TypeError: 'type' object does not support item deletion"