2013-11-27 4 views
1

Я бы хотел использовать __delitem__ с переменной уровня класса. Мой вариант использования можно найти here (ответ, который использует _reg_funcs), но в основном он включает класс декоратора, содержащий список всех функций, которые он украсил. Есть ли способ получить объект класса для поддержки __delitem__? Я знаю, что для этой цели я мог бы специально создать экземпляр, но я бы предпочел не делать этого.Использование __delitem__ с объектом класса, а не экземпляром в Python

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" 

ответ

2

Когда вы пишете del obj[key], Python называет __delitem__ метод класса obj, не obj. Таким образом, del obj[key] приводит к type(obj).__delitem__(obj, key). В этом случае type(Foo).__delitem__(Foo, 'abcd'). type(Foo): type и type.__delitem__ не определен. Вы не можете самостоятельно изменить type, вам нужно будет изменить тип Foo на то, что делает.

Вы что, определив новую метакласса, который просто подкласс type, то инструктаж Python использовать новый метакласс для создания Foo класса (а не экземпляры Foo, но сам Foo).

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) 

Изменение метакласса Foo от type к ClassMapping обеспечивает Foo с

  1. некоторого класс переменной _instances, который относится к словарю
  2. __delitem__ метода, который удаляет аргументы из _instances.
+0

Работы, спасибо. Но я удивлен, что «когда вы пишете del obj [key], Python вызывает метод __delitem__ класса obj, а не obj». Почему это? – kuzzooroo

+1

Как и любой метод, функция привязывается к классу, а не к объекту, а объект является неявным первым аргументом функции. Попытка сделать метод '__delitem__' методом класса вместо обычного метода экземпляра будет особым случаем, который Python просто не реализует. – chepner

Смежные вопросы