2011-07-16 67 views
12

我需要使用None初始化實例的所有插槽。我如何獲得派生類的所有插槽?獲取派生類的所有__slots__

例(其中不工作):

class A(object): 
    __slots__ = "a" 

    def __init__(self): 
     # this does not work for inherited classes 
     for slot in type(self).__slots__: 
      setattr(self, slot, None) 

class B(A): 
    __slots__ = "b" 

我可以用持有的插槽一個附加的類屬性(包括繼承)的所有類,像

class A(object): 
    __slots__ = "a" 
    all_slots = "a" 

    def __init__(self): 
     # this does not work for inherited classes 
     for slot in type(self).all_slots: 
      setattr(self, slot, None) 

class B(A): 
    __slots__ = "b" 
    all_slots = ["a", "b"] 

,但似乎次優的。

任何意見都表示讚賞!

乾杯,

+1

爲什麼你需要'__slots__' –

+1

我使用這些類來處理客戶端的JSON商業項目(」標籤「:richt客戶端,PyQt,通過描述符進行屬性訪問,引用的延遲解析,類型驗證)。我有多達100萬個這樣的對象,因此內存需求可能是一個問題(即使我現在沒有合適的真實世界數據 - 我知道你在想什麼......所有邪惡的根源......; ))。但我也需要禁止任何動態屬性的創建。這確保在將新創建的對象提交回服務器時沒有「垃圾」屬性。 – Knack

回答

11

首先,它是

class A(object): 
    __slots__ = ('a',) 
class B(A): 
    __slots__ = ('b',) 

製作包含由B的__slots__或其任何父類包含的所有元素將是一個列表:

from itertools import chain 
slots = chain.from_iterable(getattr(cls, '__slots__', []) for cls in B.__mro__) 
+0

爲什麼碰'__mro__' –

+0

謝謝!這很好。而且我第一次在我的代碼中使用鏈接! – Knack

+1

這不太對。一個屬性可能出現在多個地方的__slots__中,例如在父母和孩子中。因此,您生成的插槽迭代器可以具有相同屬性的多個副本。可以做一些類似於'b.s__類中的cls'__.__ mro__:slots.update(getattr(cls,「__ slots __」,[]))'其中slot是某個對象,如集合。 –

7

您想遍歷0123中的每個類:

class A(object): 
    __slots__ = ('x', 'y') 
    def __init__(self): 
     for slots in [getattr(cls, '__slots__', []) for cls in type(self).__mro__]: 
      for attr in slots: 
       setattr(self, attr, None) 

你可以看到,這個工程預期在派生類中:

class B(A): 
    __slots__ = ('z',) 

>>> b = B() 

>>> b.x, b.y, b.z 
<<< (None, None, None) 
+0

感謝您的答案。 MRO是失蹤的一塊。 – Knack

相關問題