2011-07-16 50 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

あなたは –

+1

__slots__' '必要がありますか私は、クライアント上のJSONのビジネスアイテムを処理するために、これらのクラスを使用する理由(」タグ ":リッチクライアント、PyQt、記述子による属性アクセス、参照の遅延解決、タイプ検証)。私はこれらのオブジェクトを100万個まで持っているので、メモリ要件が問題になるかもしれません(現実世界のデータが適切でない場合でも - あなたが思っていることを知っています...すべての悪の根源... - ))。しかし、動的な属性の作成も禁止する必要があります。これにより、新しく作成されたオブジェクトをサーバーにコミットするときに「ガベージ」属性がないことが確認されます。 – Knack

答えて

11

まず、それは次のようになりBの__slots__またはその親クラスのいずれかに含まれるすべての要素を含むリストを作成

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

です:

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

なぜタッチ '__mro__' –

+0

ありがとう!それは気の利いたものだ。私のコードでチェーンを使うのは初めてです! – Knack

+1

これは正しくない。属性が複数の場所で '__slots__ 'に表示される可能性があります。親と子にしたがって、生成するスロットイテレータには、同じ属性の複数のコピーを含めることができます。 slot.update(getattr(cls、 "__ slots __"、[])) 'ここで、slotsはセットのようないくつかのオブジェクトです。 –

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

関連する問題