クラスの定義でwith_metaclass()
呼び出しが何を意味するのかを聞きたいです。
例えば。:
class Foo(with_metaclass(Cls1, Cls2)):
with_metaclass()
は、 six
ライブラリ が提供するユーティリティクラスファクトリ関数で、Python 2および3。
一時的なメタクラスで少し手を使用して(以下を参照)、Python 2とPython 3。
ドキュメントから引用:
基本クラスbaseとメタクラスmetaclassを使用して新しいクラスを作成します。これは、次のようなクラス宣言で使用されるように設計されています。
from six import with_metaclass class Meta(type): pass class Base(object): pass class MyClass(with_metaclass(Meta, Base)): pass
メタクラスをアタッチする構文がPython 2と3の間で変更されたため、これが必要です。
Python 2:
class MyClass(object):
__metaclass__ = Meta
Python 3:
class MyClass(metaclass=Meta):
pass
with_metaclass()
関数は、メタクラスがa)サブクラスに継承され、b)メタクラスを使用して新しいクラスを生成できること、およびc)メタクラスを持つ基本クラスからサブクラスを作成すると、実際のサブクラスオブジェクトはメタクラスに委任されます。一時的なmetaclass
メタクラスを持つ新しい一時的な基本クラスを効果的に作成します。サブクラスの作成に使用すると、swaps out一時的な基本クラスとメタクラスを選択したメタクラスと組み合わせます。
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
# This requires a bit of explanation: the basic idea is to make a dummy
# metaclass for one level of class instantiation that replaces itself with
# the actual metaclass.
class metaclass(type):
def __new__(cls, name, this_bases, d):
return meta(name, bases, d)
@classmethod
def __prepare__(cls, name, this_bases):
return meta.__prepare__(name, bases)
return type.__new__(metaclass, 'temporary_class', (), {})
上記の内訳:
type.__new__(metaclass, 'temporary_class', (), {})
はmetaclass
メタクラスを使用して、temporary_class
という名前の新しいクラスオブジェクトを作成します。 type.__new__(metaclass, ...)
の代わりにmetaclass(...)
を使用して、次のステップでのわずかな作業に必要な特別なmetaclass.__new__()
実装の使用を回避します。temporary_class
が基本クラスとして使用される場合、Python最初の呼び出しmetaclass.__prepare__()
(派生クラス名、(temporary_class,)
this_bases
引数としてintendedメタクラスmeta
を使用してmeta.__prepare__()
を呼び出し、this_bases
を無視してbases
引数を渡します。metaclass.__prepare__()
の戻り値をクラス属性のベース名前空間として使用した後(またはPython 2)の場合は単純な辞書を使用します)、Pythonは、実際のクラスを作成するためにmetaclass.__new__()
を呼び出します。これは(temporary_class,)
としてthis_bases
タプルとして渡されますが、上記のコードはこれを無視し、代わりにbases
を使用してmeta(name, bases, d)
新しい派生クラスを作成します。その結果、with_metaclass()
を使用すると、新しいクラスオブジェクトが得られます追加の基本クラスなし:
>>> class FooMeta(type): pass
...
>>> with_metaclass(FooMeta) # returns a temporary_class object
<class '__main__.temporary_class'>
>>> type(with_metaclass(FooMeta)) # which has a custom metaclass
<class '__main__.metaclass'>
>>> class Foo(with_metaclass(FooMeta)): pass
...
>>> Foo.__mro__ # no extra base classes
(<class '__main__.Foo'>, <type 'object'>)
>>> type(Foo) # correct metaclass
<class '__main__.FooMeta'>
[〜#〜] update [〜#〜]:six.with_metaclass()
関数はその後、デコレータバリアント、つまり@six.add_metaclass()
。この更新プログラムは、ベースオブジェクトに関連するいくつかのmroの問題を修正します。新しいデコレータは次のように適用されます。
import six
@six.add_metaclass(Meta)
class MyClass(Base):
pass
ここにパッチノートがあります および 同様の詳細な例と説明があります 代替デコレータを使用します。