__metaclass__って何?メモ

Python__metaclass__ の理解を深めるメモ。

Python 和訳ドキュメント3.3.3 クラス生成をカスタマイズする を見てみると、

  • そのクラスに対するメタクラスを指定。
  • デフォルトは type
  • 可能性は無限大。

との事。 とりあえず、どのタイミングでメタクラスがクラスを書き換えるのかをテスト。

>>> # メタクラスを定義。
>>> class Meta(type):
...     def __new__(cls, name, bases, dicts):
...         # 呼び出しタイミングを取る為にprintする。
...         print "'__new__' has been called."
...         return super(Meta, cls).__new__(cls, name, bases, dicts)
...
>>>
>>> # Metaをメタクラスに持つHigeを定義。
>>> class Hige(object):
...     __metaclass__ = Meta
...     pass
...
'__new__' has been called. # <--- ココでprintされる。

Python 和訳ドキュメント に書かれてる通り、クラスが生成される前に呼び出されているのが分かる。ここでHigeを継承したクラスも定義してみる。

>>> # Higeを継承したMageを定義。
>>> class Mage(Hige):
...     pass
...
'__new__' has been called. # <-- 同じくprintされる。

子クラスにもちゃんと反映されていて、その都度呼び出されている。PHPには無い挙動なので、理解するのにちょっと時間がかかる。

理解を深める為に、 Python 和訳ドキュメント に書かれているインターフェイスチェックとかやってみる。

>>> # メタクラスを定義。
>>> class Meta(type):
...     def __new__(cls, name, bases, dicts):
...         cls = super(Meta, cls).__new__(cls, name, bases, dicts)
...         # saveメソッドを持っているかチェック。
...         if not hasattr(cls, 'save'):
...             raise AttributeError("'save' is not implemented.")
...         return cls
...
>>> # saveメソッドを持たせずにHigeを定義。
>>> class Hige(object):
...     __metaclass__ = Meta
...     pass
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __new__
AttributeError: 'save' is not implemented.
>>>
>>> # 今度はsaveメソッドを持たせてHigeを定義。
>>> class Hige(object):
...     __metaclass__ = Meta
...     def save(self):
...         print 'save!!'
...
>>> # エラーは出ない。

あんまり意味の無いテストなものの、何となく見えてきた気がする。かな? まだ自分で書く事はないものの、分かってないとソースが追いかけれない。

ちょっと実装例を探してみると、 inforno さんの Python:アクセサの生成 を発見。なるほど。こういう事が出来るのか。と納得。

うーむ、 Python は奥が深い。勉強しよ。

Posted at: 
2007/09/12 02:30:38
0 Comments
0 TrackBacks
Tags: 
Python
Trackback: 
http://humming.via-kitchen.com/2007/09/12/metaclass-memo/trackback/

TrackBacks

まだ登録されていません。

Comments

まだ登録されていません。

Add Comment

Add Comment