1

ZODB に永続化されるクラスがたくさんあります。すべてのクラスはいくつかのインデックス機能を共有する必要がありますが、すべてのクラスで多くのプロパティが定義されています。プロパティは記述子を使用してクラス レベルで定義され、検証のためにそれらへの書き込みをインターセプトし、DB 内の重複をチェックできます。このために、すべてのクラスには、自動的に維持されるプロパティのリストがあります_properties。それらはまた_indices、すべての単一の要素クラス (約 10 程度) に自分でコピーしたくない他の機能も保持します。

次のコードを検討してください。

class BaseElement(object):
    _properties = None

class ElementFlavour1(BaseElement):
    _properties = 'a', 'b', 'c'

....

class ElementFlavourN(BaseElement):
    _properties = 'e', 'f', 'g'

for item in locals():
    if issubclass(item, BaseElement):
        item._v_properties_set = set(item._properties) if item._properties else set()

したがって、基本的には本来の処理を実行します。直線的に反復する必要があり_propertiesますが、クラスにプロパティが存在する場合は、クイック ルックアップも実行したいと考えています。BaseElementそれにもかかわらず、私は自分自身を繰り返して、明示的にすべてのフレーバーに対してこのセットを指定したくありません。

現在の解決策はうまくいきますが、私はそれを醜いハックと考えており、それを取り除きたいと思っています. たとえば、他のモジュールのサブクラスではBaseElement、プロパティが正しく設定されません。__new__クラスの構築を傍受するのではなく、インスタンス化を傍受するため、いじってみるのも間違った方法のようです。では、それを適切に行うにはどうすればよいでしょうか。

PS私はOrderedDictを知っていますが、これは私が探しているものではありません。クラス作成プロセスにクリーンな方法でフックし、そこに任意の機能を追加したいと思います。

4

1 に答える 1

4

メタクラスでこれを行うことができます:

class BaseType(type):
    def __init__(cls, name, bases, clsdict):
        super(BaseType, cls).__init__(name, bases, clsdict)
        setattr(cls,'_v_properties_set',
                set(cls._properties) if cls._properties else set())

class BaseElement(object):
    __metaclass__ = BaseType    
    _properties = None

class ElementFlavour1(BaseElement):
    _properties = 'a', 'b', 'c'

class ElementFlavourN(BaseElement):
    _properties = 'e', 'f', 'g'

print(ElementFlavourN._v_properties_set)
# set(['e', 'g', 'f'])

クラス デコレータを使用してこれを行うこともできますが、各サブクラスをBaseElement個別に装飾する必要があります。メタクラスは継承されるため、一度定義するだけで済みます。

于 2012-09-29T09:50:28.693 に答える