2013-11-27 31 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

相關問題