記事一覧:2009年06月18日

Pythonのクラスの挙動を調べる:class構文の外からクラスにメンバ関数を追加(1)

Pythonのクラスの挙動を調べる:class構文の外からクラスにメンバ関数を追加(1)

 Pythonでプラグイン的な機構を実装する際、あるモジュールで定義されたクラスに対し、ほかのモジュールからメンバ関数を追加できると楽しいのでは?とふと思う。

 ちょっと分かりにくいが、例えばHogeというクラスがhoge.pyで定義されており、Hogeクラスのメンバ関数を追加するコードがplugin.pyで定義されている。そして、plugin.pyで定義されている機能を使いたい場合のみimport pluginすると、その機能がHogeクラスで利用できるようになる、というイメージだ。

 ということで、ちょっと試してみた。

[Macintosh:~]$ python
Python 2.5.1 (r251:54863, Feb  6 2009, 19:02:12)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

   # 適当な関数を定義 

>>> class FooBar(object):
...     def func1(self):
...             print "func1!"
...     def func2(self):
...             print "func2!"
...

   # FooBarクラスのインスタンスを作成 

>>> a = FooBar()
>>> a.func1()
func1!
>>> a.func2()
func2!

   # FooBarは__main___内にクラスオブジェクトして記録される 

>>> locals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__':
'__main__', '__doc__': None, 'a': <__main__.FooBar object at
0x2454f0>, 'FooBar': <class '__main__.FooBar'>}
>>> print FooBar
<class '__main__.FooBar'>
>>> print FooBar.__dict__
{'func2': <function func2 at 0x5e2f0>, '__module__': '__main__',
'func1': <function func1 at 0x5e2b0>, '__dict__': <attribute
'__dict__' of 'FooBar' objects>, '__weakref__': <attribute
'__weakref__' of 'FooBar' objects>, '__doc__': None}

   # FooBarクラスに追加する関数を定義 

>>> def add1(self):
...     print "add1!"
...

   # add1関数をFooBarクラスのメンバに追加 

>>> FooBar.add1 = add1

   # クラスを改変する前に作成したインスタンスも影響を受ける! 

>>> a.add1()
add1!
>>> print FooBar.__dict__
{'func2': <function func2 at 0x5e2f0>, '__module__': '__main__',
'add1': <function add1 at 0x5e270>, 'func1': <function func1 at
0x5e2b0>, '__dict__': <attribute '__dict__' of 'FooBar' objects>,
'__weakref__': <attribute '__weakref__' of 'FooBar' objects>,
'__doc__': None}
>>>

 ということで、少なくともクラスオブジェクトに対して属性を追加することで、クラスにメンバ関数を追加できることは分かりました。なるほどなるほど。