欲しくなったときに毎回作ってるので、書いて放り投げておく。
精度はそんなこだわって無くて、どっちかと言うと使いやすさに気を使ってみた。
デコレータ作っちゃおうぜ
計測したいメソッドの中や前後にうろちょろデバッグ処理書くのは見通しが悪くなるので、@measure
とか作ってみる。
def measure(label, times):
def _measure(func):
def wrapper(*args):
print label
for x in xrange(1, 1 + times):
t1 = time() * 1000
result = func(*args)
t2 = time() * 1000
print ' %02d: %d msec' % (x, (t2 - t1))
return result
return wrapper
return _measure
こんなのをどっかに置いといて、
from time import sleep
@measure(label = 'foo 1', times = 3)
def foo(n, s):
sleep(0.5)
return 'n: %(n)d, s: %(s)s' % locals()
こんな感じでアノテートする。
そうするとこんな感じに指定回数実行されて、本来の戻り値が返される。
>>> print foo(3, 5)
foo 1
01: 500 msec
02: 500 msec
03: 500 msec
n: 3, s: 5
こんだけ。
絶対にもっとちゃんとしたのがあるけど、ライブラリ入れてちゃんと計るほどでもない自分のおもちゃに対してとかは、十分役に立つしコードを汚さないので良い感じ。
デコレータ補足
python のデコレータは関数渡しさえ知っていれば、一度理解してしまえば案外難しくない。
これは@measure
が引数を取れるためにmeasure
の下に_measure
を置いているのがちょっと複雑に見えるけど、
要は@measure(label = 'foo 1', times = 3)
が終わったときにfunc
を受ける関数が返れば良いだけ。
デコレータは装飾している関数を引数に取れば良いので、そこを気にしていれば多分大丈夫。
沢山良い記事があるのでデコレータについては割愛するけど、以下の最低機能の形を理解すればあとは書いたり調べたりは応用が利くはず。
def simple_measure(func):
def wrapper():
print 'start'
func()
print 'end'
return wrapper
@simple_measure
def simple_foo():
print 'simple_foo'
>>> simple_foo()
start
simple_foo
end
おしまい。