2

私は既存のDjangoライブラリを使用しており、抽象化したいクラスを作成しています。

問題のクラスがであるとしましょうBaseFoo

現在、実装には基本クラスがありBaseFooます。

拡張するクラスが作成されるたびBaseFooに、メタクラスはそれをクラスのリストに追加します。BaseFooクラス名のハードコードされたテストを実行しても、明示的に追加されません。

    if name not in ('BaseFoo',):
        class_list.append(new_cls)

私は次のようなものを書けるようになりたいです:

class MyBaseFoo(BaseFoo):
    class Meta:
        abstract = True

そして、メタクラスBaseFooに抽象であるすべてのオブジェクトをスキップさせます。ですから、Djangoがモデルで同じことをどのように行うのか、そしてこれを自分で行うための簡単でエレガントな方法があるのか​​どうか疑問に思っていると思います。

Djangoがモデルを定義するために使用するコードのいくつかを調べましたが、いくつかのポインターを使用することもできます。また、必ずしも使用せずにこれを行うさらに簡単な方法がある場合は、class Meta私もそれを受け入れます。

私はこの解決策に特に興奮していないことに注意してください:

class MyBaseFoo(BaseFoo):
    abstract = True

class ActualFoo1(MyBaseFoo):
    abstract = False

class ActualFoo2(MyBaseFoo):
    abstract = False
4

1 に答える 1

3

具象クラスで抽象をFalseに設定する必要はありません。この設定は、抽象クラスでのみ行うだけで十分です。

class_list = []
class CollectSubclasses(type):
    def __new__(cls, name, bases, attrs):
        abstract = False
        if attrs.get('abstract', False):
            abstract = True
            del attrs['abstract']
        res = super(CollectSubclasses, cls).__new__(cls, name, bases, attrs)
        if not abstract:
            class_list.append(res)
        return res

class BaseFoo(object):
    __metaclass__ = CollectSubclasses
    abstract = True

class Concrete1(BaseFoo):
    pass

class Abstract(BaseFoo):
    abstract = True

class Concrete2(Abstract):
    pass

print class_list

別の方法としてPython2.6のクラスデコレータを使用することもできますが、デコレータが呼び出されたときにクラスがすでに作成されているため(したがって、メタクラスがすでに呼び出されているため)、@abstractデコレータのclass_listからクラスを削除する必要があります。

于 2010-12-27T20:30:01.950 に答える