やや柔軟なFactory
apply()とgetattr()を使って、Factory作るための簡単な実験を行ってみた。
Hoge classと、Fuga classを動的にinstance化して、prn()メソッドを叩く実験を行ってみたので、作り方と結果を以下に記載する。
準備
Hogeクラスと、Fugaクラスを作成。両クラス名を持つリストを用意。
このリストを利用して、クラスを動的に生成する。
class Hoge(): def prn(self): print self.__class__.__name__ class Fuga(): def prn(self): print self.__class__.__name__ klasses = [Hoge, Fuga]
apply()でつくる場合
"初めてのpython(第3版)"にも載っている例(に近い物)。
コード
for klass in klasses: kls = apply(klass) # class名で直にいける,klsにはinstanceが入る kls.prn()
実行結果
Hoge Fuga
getattr()でつくる場合
インポート先も動的に指定してクラスを取得し、instance化したいときにいけるかも。
コード
import __main__ klasses = [Hoge, Fuga] for klass in klasses: kls = getattr(__main__, klass.__name__)() # クラス名はstringで呼ばないといけない(※) kls.prn()
実行結果
Hoge Fuga
余談
※試みに、以下のようにしたが、これだと動作しなかった
コード
import __main__ klasses = [Hoge, Fuga] for klass in klasses: # kls = getattr(__main__, klass.__name__) # kls().prn() kls = getattr(__main__, klass.__init__) kls.prn()
実行結果
$ ./create_meta_object.py | Traceback (most recent call last): File "./create_meta_object.py", line 30, in <module> kls = getattr(__main__, klass.__init__) AttributeError: class Hoge has no attribute '__init__'
なぜ、(constructorである)'__init__'が無いと怒られるのかが良く理解できていない。
結果を受けて、試みに、def __init__(self):pass をつけてみたが、別のエラーが出て本日は断念。分かったら後日報告したい。
追記(2012/03/07 Mi.)
(当たり前だけど)もっと単純にこれで良かったのか...。
しょうもないところで時間かけてしまったorz
コード
klasses = [Hoge, Fuga] for klass in klasses: kls = klass() kls.prn()
実行結果
$ ./create_meta_object.py Hoge Fuga
Factoryへの応用
Factoryの中で指定されたパラメータに応じて生成するクラスを動的に切り替える時には、klassesでリストを使用した代わりに、辞書を使用する、や、あるdir配下のmoduleから自動でクラス名を取得して利用する等、色々応用が効きそうです。
直接クラス名を指定せずに、instance化出来るのが簡単にできて使い勝手が良さそうです。
(調べるのは時間かかったけど)
- 作者: Mark Lutz,夏目大
- 出版社/メーカー: オライリージャパン
- 発売日: 2009/02/26
- メディア: 大型本
- 購入: 12人 クリック: 423回
- この商品を含むブログ (133件) を見る