contextlibとか__import__とかfunctoolsとか
Temporary substitution of object in modules via with statement « Python recipes « ActiveState Code
Active StateのPython Recipesですごく勉強になるレシピを見つけた。
これは、with文で任意のモジュールの属性を一時的に書き換えてしまう例。
このレシピを読むと、
- contextlib, with文の利用例
- __import__ マジックメソッドの使い方
- functools.partialの使い方
が一度に学べる(学ぶきっかけが得られる?)。
これはとてもお得!
contextlib: with文を活用する
「コンテキストマネージャ」というものを作ってwith文で使える。
組み込みのコンテキストマネージャもいくつかあるみたい。
超有名なのはclosingかな♡
よくファイルとかデータベースのコネクションのcloseメソッドをtry-finallyブロックを使って呼ぶけど、それをwith文で書けるのがclosing。
http://www.python.jp/doc/nightly/library/contextlib.html#contextlib.closing
with closing(open("takumi.txt", "r")) as f: print f.read()
必ずcloseが呼ばれます☆
こんな風に、with文をうまく活用するための仕組みがcontextlibモジュールみたい。
Python Recipeの例では、モジュールの差し替えをやらせている。
__import__マジックメソッド
http://d.hatena.ne.jp/perezvon/20080129/1201623922
ここでは__import__のことが詳しく考察されているけど(ちょっと僕のレベルだと意味が解らない..)、
- __import__を使うとモジュールの名前を文字列で渡してインポートできる。
- インポートは最初の1回やったら再度ロードし直さない。
- でもreload関数を使うと何度もインポートし直せる。
ってことは判った。
それで、Python Recipeでは
def _findattr(mod, rest): parent, dot, rest = rest.partition('.') if rest: return _findattr(getattr(mod, parent), rest) else: return mod, parent def find_in_module(fullname): modname, dot, rest = fullname.partition('.') module, objname = _findattr(__import__(modname), rest) return getattr(module, objname), partial(setattr, module, objname)
こういう風に、モジュールをインポートして望みの属性に辿りつくまでgetattrを繰り返すんだね。
functools.partial: 引数の部分適用をする
pythonの関数は第1級オブジェクトなので、関数を引数に取ったり関数を返す関数を作ったりできる。
そして、関数の引数を部分適用した関数を作ることもできる。
例えば、
def foo(x, y): return x + y import functools bar = functools.partial(foo, 1) print bar(8) #=> 9
こんな感じかな。
このコードのbarみたいに、fooの第1引数を1で固定した別の関数を作るっていうのが部分適用。
Python Recipeでは
partial(setattr, module, objname)
こんなことをしている。
最初見たときすぐには意味が解らなかったんだけど、settattr関数は「オブジェクト・属性名・属性値」の順に引数を取って、対象のオブジェクトの属性に代入を行うので、「オブジェクト・属性名」まで束縛した新しい別の関数を作っているってことなんだね。
そして後ろの行でpartialで作った関数に差し替えたい値を渡している。
それと、文字列にpartitionっていうメソッドがあることも初めて知った。
色々ためになるな〜と思った。