11.5.2.メタクラスの基本
メタクラスとは?

メタクラスはクラスのクラスとも呼ばれ、クラスの挙動を制御するために使われます。つまり、クラスはオブジェクトを作成するための設計図のようなものであるのに対して、メタクラスはクラスを作成するための設計図と言えます。

Pythonでは、typeが最も基本的なメタクラスです。typeは通常、オブジェクトの型を確認するために使われますが、type自体もクラスを作成するために使うことができます。そのため、typeは実質的にすべてのクラスのメタクラスであり、すべてのクラスはtypeから派生しています。

しかし、多くの場合、開発者が直接メタクラスを扱うことは少ないです。それは、メタクラスがクラスの挙動を大幅に変更するため、コードの理解を難しくし、予期せぬ副作用を引き起こす可能性があるからです。したがって、メタクラスは必要なとき、そしてそれを正しく扱えるときにのみ使用すべきと言われています。


>>> class MyMeta(type):
...    @classmethod
...    def __prepare__(matacls, name, bases, **kwargs):
...       print(f'{matacls}:__prepare__')
...       #return super().__prepare__(name, bases, **kwargs)
...       return {'hoge': 'ほげ'}
...    def __new__(matacls, name, bases, disc, **kwargs):
...       print(f'{matacls}:__new__')
...       return super().__new__(matacls, name, bases, disc)
...    def __init__(cls, name, bases, disc, **kwargs):
...       print(f'{cls}:__call__')
...       super().__init__(name, bases, disc)
...    def __call__(cls, *args, **kwargs):
...       print(f'{cls}:__call__')
...       return super().__call__(*args, **kwargs)
...
>>> class MyClass(metaclass=MyMeta):
...    pass
...
<class '__main__.MyMeta'>:__prepare__
<class '__main__.MyMeta'>:__new__
<class '__main__.MyClass'>:__call__
>>> if __name__ == '__main__':
...    c = MyClass()
...    print(MyClass.hoge)
...
<class '__main__.MyClass'>:__call__
ほげ
>>>

  1. 1.メタクラス MyMeta の定義:

    • Pythonのクラスは、実は背後でtypeというメタクラスによって動作しています。ここで定義されているMyMetaは、新しいクラスの作成時に呼び出される特殊メソッドを持つカスタムメタクラスです。

  2. 2.__prepare__
    メソッド
    :

    • このメソッドは、新しいクラスの名前空間を生成するために使用されます。
    • {'hoge': 'ほげ'} という辞書を返しているので、この名前空間には初めから hoge というキーが存在します。

  3. 3.__new__
    メソッド
    :

    • クラスオブジェクトの実際の作成を担当するメソッドです。
    • このメソッドが呼び出されると、新しいクラスオブジェクトが作成されます。

  4. 4.__init__
    メソッド
    :

    • 新しく作成されたクラスオブジェクトを初期化するメソッドです。
    • このメソッド内でクラスオブジェクトは既に存在しているため、属性の追加や初期設定を行うことができます。

  5. 5.__call__
    メソッド
    :

    • クラスオブジェクトが"呼び出し可能"として動作する際に実行されるメソッドです。
    • 例えば、MyClass() のようにクラスをインスタンス化するときや、クラスオブジェクト自体を関数のように呼び出す際に実行されます。

  6. 6.MyClass
    の定義とインスタンス化
    :

    • MyClass が定義される際に、上で述べたMyMeta__prepare____new____init__が順に呼び出されます。
    • c = MyClass() という行でMyClassのインスタンスを生成しようとすると、__call__ メソッドが呼び出されます。

  7. 7.出力結果の確認
    :

    • print(MyClass.hoge) の結果として ほげ が出力されます。これは__prepare__ メソッドで初期名前空間として {'hoge': 'ほげ'} を返しているためです。

このように、メタクラスを利用することで、クラスの生成や動作のプロセスをカスタマイズすることができます。



メタクラスの主なメソッド
メソッド 概要
__prepare__ クラス定義(type関数の引数dictに相当)を生成。規定は空の辞書(クラスメソッド)
__new__ メタクラスによるインスタンス(実クラス)生成時に呼び出し
__init__ メタクラスによるインスタンス(実クラス)初期化時に呼び出し
__call__ メタクラスのインスタンス(実クラス)が呼び出されて時に呼び出し


構文 クラスの定義(メタクラス付き)
class クラス名(metaclass=メタクラス名):~


構文 クラスの定義(メタクラス付き、ほかのクラスを継承)
class クラス名(基底クラス、..., metaclass=メタクラス名):~