概念的には、クラスは一連のオブジェクト (クラスのインスタンス) に共通するものを定義するために存在します。それで全部です。クラスによって定義された共有パターンに従って、クラスのインスタンスについて考えることができます。すべてのオブジェクトが異なる場合、わざわざクラスを使用するのではなく、辞書を使用するだけです。
メタクラスは通常のクラスであり、同じ理由で存在します。そのインスタンスに共通するものを定義します。デフォルトのメタクラスtype
は、クラスとインスタンスを慣れ親しんだ方法で動作させる通常のルールをすべて提供します。
- インスタンスの属性検索では、インスタンス、そのクラス、すべてのスーパークラスが MRO 順にチェックされます。
MyClass(*args, **kwargs)
invokesを呼び出しi = MyClass.__new__(MyClass, *args, **kwargs)
てインスタンスを取得してから、invokesi.__init__(*args, **kwargs)
を呼び出して初期化します
- クラスは、クラス ブロックでバインドされたすべての名前をクラスの属性にすることによって、クラス ブロック内の定義から作成されます。
- 等
通常のクラスとは異なる動作をするいくつかのクラスが必要な場合は、メタクラスを定義して、通常とは異なるクラスをtype
. おそらく、異なる種類のクラスを完全type
に異なるものにしたくないので、メタクラスはほぼ確実に のサブクラスになります。ブックのサブセットの動作を少し変えて (たとえば、他の作品の編集物であるブック) 、完全に異なるクラスではなく のサブクラスを使用したい場合と同様です。Book
一部のクラスを通常のクラスとは異なる方法で動作させる方法を定義しようとしていない場合、メタクラスはおそらく最適なソリューションではありません。「インスタンスがどのように機能するかをクラスが定義する」ことは、すでに非常に柔軟で抽象的なパラダイムであることに注意してください。ほとんどの場合、クラスの動作を変更する必要はありません。
グーグルで検索すると、クラスの作成に関連する多くのことを実行するために実際に使用されているメタクラスの例がたくさん表示されます。多くの場合、クラス属性を自動的に処理したり、どこかから自動的に新しいものを見つけたりします。メタクラスの優れた使用法とは言えません。クラスの動作を変更しているのではなく、一部のクラスを処理しているだけです。私の意見では、クラスを作成するためのファクトリ関数、またはクラスの作成直後に呼び出すクラス メソッド、または何よりもクラス デコレータは、この種のものを実装するためのより良い方法です。
しかし、Python のクラスの既定の動作を概念的に単純なものにするために、複雑なコードを記述していることに気付くことがあります。実際には、「さらに踏み込んで」それをメタクラス レベルで実装するのに役立ちます。
かなり些細な例は「シングルトン パターン」です。ここでは、インスタンスが 1 つしか存在できないクラスがあります。クラスを呼び出すと、インスタンスが既に作成されている場合は既存のインスタンスが返されます。個人的に私はシングルトンに反対であり、その使用についてはアドバイスしません (それらはグローバル変数であり、微妙なバグを引き起こす可能性をさらに高めるために、新しく作成されたインスタンスのように巧妙に偽装されていると思います)。しかし、人々はそれらを使用しており、 と を使用してシングルトン クラスを作成するための膨大な数のレシピが__new__
あり__init__
ます。このようにすると、少しイライラすることがあります。これは主に、Python が呼び出してから呼び出したいためです__new__
。__init__
その結果、誰かがシングルトンへのアクセスを要求するたびに初期化コードを再実行しない方法を見つける必要があります。しかし、クラスを呼び出したときに何をしたいのかを Python に直接伝えることができれば、Python がやりたいことを設定して最終的にやりたいことをやらせるよりも簡単ではないでしょうか?
class Singleton(type):
def __init__(self, *args, **kwargs):
super(Singleton, self).__init__(*args, **kwargs)
self.__instance = None
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super(Singleton, self).__call__(*args, **kwargs)
return self.__instance
10 行未満で、 を追加するだけで通常のクラスをシングルトンに変換します__metaclass__ = Singleton
。つまり、シングルトンであることを宣言するだけです。クラスレベルで何かを直接ハッキングするよりも、このレベルでこの種のものを実装する方が簡単です。
しかし、あなたの特定Book
のクラスについては、メタクラスによって助けられる何かをする必要はないようです。クラスがどのように機能するかの通常のルールが、単純な方法で単純であるべきことを行うことを妨げていることが判明しない限り、実際にメタクラスに到達する必要はありませんこれらすべてのクラスに多くのタイプを入力する必要があるため、共通ビットを自動生成できないだろうか?")。実際、仕事で毎日 Python を使用しているにもかかわらず、実際にメタクラスを実際に使用したことはありません。私のメタクラスはすべて、上記のようなおもちゃの例であるSingleton
か、ばかげた探索です。