4

class X独自のメタクラスを持つクラスから派生したaがありますMeta。また、SQLAlchemyの宣言型ベースからXを導出したいと思います。しかし、私は単純なことはできません

def class MyBase(metaclass = Meta):
    #...

def class X(declarative_base(), MyBase):
    #...

メタクラスの競合エラーが発生するため、「派生クラスのメタクラスは、そのすべてのベースのメタクラスの(厳密ではない)サブクラスである必要があります」。Metaと、宣言型ベースが使用するメタクラス(DeclarativeMetaだと思いますか?)の両方から派生する新しいメタクラスを作成する必要があることを理解しています。だから、書くだけで十分です:

def class NewMeta(Meta, DeclarativeMeta): pass
def class MyBase(metaclass = NewMeta):
    #...
def class X(declarative_base(), MyBase):
    #...

私はこれを試しましたが、うまくいくようです。しかし、私はこのコードに何らかの問題を引き起こしたのではないかと心配しています。

マニュアルを読みましたが、少しわかりにくいです。何ですか

編集:

私のクラスに使用されるコードは次のとおりです。

class IterRegistry(type):
    def __new__(cls, name, bases, attr):
        attr['_registry'] = {}
        attr['_frozen'] = False
        print(name, bases)
        print(type(cls))
        return type.__new__(cls, name, bases, attr)
    def __iter__(cls):
        return iter(cls._registry.values())

class SQLEnumMeta(IterRegistry, DeclarativeMeta): pass  

class EnumType(metaclass = IterRegistry):
    def __init__(self, token):
        if hasattr(self, 'token'):
            return
        self.token = token
        self.id = len(type(self)._registry)
        type(self)._registry[token] = self

    def __new__(cls, token):
        if token in cls._registry:
            return cls._registry[token]
        else:
            if cls._frozen:
                raise TypeError('No more instances allowed')
            else:
                return object.__new__(cls)

    @classmethod
    def freeze(cls):
        cls._frozen = True

    def __repr__(self):
        return self.token

    @classmethod
    def instance(cls, token):
        return cls._registry[token]

class C1(Base, EnumType, metaclass = SQLEnumMeta):
    __tablename__ = 'c1'
    #...
4

1 に答える 1

3

編集:これでIterRegistryとを見てDeclarativeMeta、コードは大丈夫だと思います。

IterRegistryとを定義__new____iter__、とをDeclarativeMeta定義__init____setattr__ます。重複がないため、直接呼び出す必要はありませんsuper。それでも、コードを将来にわたって利用できるようにするために、そうすることをお勧めします。


の定義を管理できますMetaか?その定義を教えていただけますか?の定義を見ない限り、うまくいくとか、うまくいかないとは言えないと思いますMeta

たとえば、Meta電話をかけないと 潜在的な問題が発生しますsuper(Meta,cls).__init__(classname, bases, dict_)

このコードを実行すると

class DeclarativeMeta(type):
    def __init__(cls, classname, bases, dict_):
        print('DeclarativeMeta')
        # if '_decl_class_registry' in cls.__dict__:
        #     return type.__init__(cls, classname, bases, dict_)       
        # _as_declarative(cls, classname, dict_)
        return type.__init__(cls, classname, bases, dict_)

class Meta(type):
    def __init__(cls, classname, bases, dict_):
        print('Meta')
        return type.__init__(cls, classname, bases, dict_)

class NewMeta(Meta,DeclarativeMeta): pass

class MyBase(object):
    __metaclass__ = NewMeta
    pass

次に、文字列のみ'Meta'が印刷されます。言い換えれば、Meta.__init__実行されるだけです。DeclarativeMeta.__init__スキップされます。

一方、あなたが定義する場合

class Meta(type):
    def __init__(cls, classname, bases, dict_):
        print('Meta')
        return super(Meta,cls).__init__(classname, bases, dict_)

その後、両方Meta.__init__DeclarativeMeta.__init__実行されます。

于 2010-09-02T11:53:28.330 に答える