3

__new__で提供された値に従って新しいクラスを作成する方法をカスタマイズするメソッドをカスタマイズするメタクラスを作成していますkwargs。これはおそらく例でより理にかなっています:

class FooMeta(type):
    def __new__(cls, name, bases, kwargs):
        # do something with the kwargs...
        # for example:
        if 'foo' in kwargs:
            kwargs.update({
                'fooattr': 'foovalue'
            })
        return super(FooMeta, cls).__new__(cls, name, bases, kwargs)

私の問題は、これを Python 2 と 3 の両方で互換性を持たせるにはどうすればよいかということです。Sixは優れた互換性ライブラリですが、私の問題は解決しません。次のように使用します。

class FooClass(six.with_metaclass(FooMeta, FooBase)):
    pass

six は指定されたメタクラスを使用して新しい基本クラスを作成するため、これは機能しません。以下は6のコードです(リンク)(1.3現在):

def with_metaclass(meta, base=object):
    return meta("NewBase", (base,), {})

その結果、私の__new__メソッドは何も呼び出されずに呼び出されるkwargsため、本質的に私の機能を「壊す」ことになります。問題は、Python 2 と 3 の両方の互換性を損なうことなく、どうすれば目的の動作を実現できるかということです。Python 2.6 のサポートは必要ないことに注意してください。Python 2.7.x と 3.x のみで何かが可能であれば、それでいい。

バックグラウンド

Djangoで動作するにはこれが必要です。モデル属性に応じてモデルの作成方法をカスタマイズするモデル ファクトリ メタクラスを作成したいと考えています。

class ModelMeta(ModelBase):
    def __new__(cls, name, bases, kwargs):
        # depending on kwargs a different model is constructed
        # ...

class FooModel(six.with_metaclass(ModelMeta, models.Model):
    # some attrs here to be passed to the metaclass
4

1 に答える 1

4

私の理解が正しければ、問題はなく、すでに機能しています。メタクラスが目的の効果を持っているかどうかを実際に確認しましたか? すでにそうなっていると思うからです。

によって返されるクラスwith_metaclassは、クラス FooClass の役割を果たすことを意図したものではありません。これは、クラスの基本クラスとして使用されるダミー クラスです。この基本クラスはメタクラス FooMeta であるため、派生クラスにもメタクラス FooMeta が含まれるため、適切な引数を使用してメタクラスが再度呼び出されます。

class FooMeta(type):
    def __new__(cls, name, bases, attrs):
        # do something with the kwargs...
        # for example:
        if 'foo' in attrs:
            attrs['fooattr'] = 'foovalue'
        return super(FooMeta, cls).__new__(cls, name, bases, attrs)
class FooBase(object):
    pass
class FooClass(with_metaclass(FooMeta, FooBase)):
    foo = "Yes"

>>> FooClass.fooattr
'foovalue'

ちなみに、 metaclass の 3 番目の引数を呼び出すのは紛らわしいkwargsです。それは実際にはキーワード引数ではありません。作成するクラスの です。つまり__dict__、クラスの属性とその値です。私の経験では、この属性は慣習的にattrsorと呼ばれていますdct(たとえば、ここここを参照)。

于 2013-05-18T22:39:36.063 に答える