2013-11-27 28 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会自动调用的不objobj__delitem__方法。所以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) 

type更改的Foo元类来ClassMapping提供Foo

  1. 类变量_instances引用字典
  2. 一个__delitem__方法从_instances移除参数。
+0

作品,谢谢。但是我很惊讶,“当你编写del obj [key]时,Python调用obj类的__delitem__方法,而不是obj。”为什么是这样? – kuzzooroo

+1

与其他方法一样,函数绑定到类,而不是对象,而对象是函数的隐式第一个参数。试图使'__delitem__'成为一个类方法而不是一个普通的实例方法,这将是Python不能实现的特殊情况。 – chepner

相关问题