Using __delitem__ with a class object rather than an instance in Python
class, class-method, instance, python
Solution
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`.
Problem
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" ```