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__
ほげ
>>>
メタクラスの主なメソッド
メソッド 概要
__prepare__ クラス定義(type関数の引数dictに相当)を生成。規定は空の辞書(クラスメソッド)
__new__ メタクラスによるインスタンス(実クラス)生成時に呼び出し
__init__ メタクラスによるインスタンス(実クラス)初期化時に呼び出し
__call__ メタクラスのインスタンス(実クラス)が呼び出されて時に呼び出し
構文 クラスの定義(メタクラス付き)
class クラス名(metaclass=メタクラス名):~
構文 クラスの定義(メタクラス付き、ほかのクラスを継承)
class クラス名(基底クラス、..., metaclass=メタクラス名):~
1.メタクラス MyMeta の定義:
- Pythonのクラスは、実は背後で
type
というメタクラスによって動作しています。ここで定義されているMyMeta
は、新しいクラスの作成時に呼び出される特殊メソッドを持つカスタムメタクラスです。
- Pythonのクラスは、実は背後で
メソッド:
2.__prepare__- このメソッドは、新しいクラスの名前空間を生成するために使用されます。
{'hoge': 'ほげ'}
という辞書を返しているので、この名前空間には初めからhoge
というキーが存在します。
メソッド:
3.__new__- クラスオブジェクトの実際の作成を担当するメソッドです。
- このメソッドが呼び出されると、新しいクラスオブジェクトが作成されます。
メソッド:
4.__init__- 新しく作成されたクラスオブジェクトを初期化するメソッドです。
- このメソッド内でクラスオブジェクトは既に存在しているため、属性の追加や初期設定を行うことができます。
メソッド:
5.__call__- クラスオブジェクトが"呼び出し可能"として動作する際に実行されるメソッドです。
- 例えば、
MyClass()
のようにクラスをインスタンス化するときや、クラスオブジェクト自体を関数のように呼び出す際に実行されます。
の定義とインスタンス化:
6.MyClassMyClass
が定義される際に、上で述べたMyMeta
の__prepare__
、__new__
、__init__
が順に呼び出されます。c = MyClass()
という行でMyClass
のインスタンスを生成しようとすると、__call__
メソッドが呼び出されます。
7.出力結果の確認:print(MyClass.hoge)
の結果としてほげ
が出力されます。これは__prepare__
メソッドで初期名前空間として{'hoge': 'ほげ'}
を返しているためです。
このように、メタクラスを利用することで、クラスの生成や動作のプロセスをカスタマイズすることができます。
メタクラスの主なメソッド
メソッド 概要
__prepare__ クラス定義(type関数の引数dictに相当)を生成。規定は空の辞書(クラスメソッド)
__new__ メタクラスによるインスタンス(実クラス)生成時に呼び出し
__init__ メタクラスによるインスタンス(実クラス)初期化時に呼び出し
__call__ メタクラスのインスタンス(実クラス)が呼び出されて時に呼び出し
構文 クラスの定義(メタクラス付き)
class クラス名(metaclass=メタクラス名):~
構文 クラスの定義(メタクラス付き、ほかのクラスを継承)
class クラス名(基底クラス、..., metaclass=メタクラス名):~
コメント