BlankTar

about | blog | works | photo

pythonにはデコレータというよく分からないものがありまして。
よく分からないので込み入った解説はしないけれど、ともかく関数をデコレーションするもののようです。

使い方は簡単 ・・・かは分からないけれど、まあそれなりに。
import time
import functools

def Timer(func):
	@functools.wraps(func)
	def Wrapper(*args, **kw):
		stime = time.clock()
		ret = func(*args, **kw)
		etime = time.clock()
		print '{0}: {1:,f}ms'.format(func.__name__, (etime-stime)*1000)
		return ret
	return Wrapper

@Timer
def Test():
	print 'hello, decorator'

Test()
こんな感じで使うと、Test関数の実行時間を測ってくれます。計測対象はいくつでもおっけー。
計りたい関数の上に一行付け足すだけだから、お手軽でいいよね。
ミリ秒単位で測ってる割に関数のオーバーヘッドを考慮してないから、あんまよろしくないですが。

デコレーターに引数を付けたい時は
import time
import functools

def Timer(name):
	def Deco(func):
		@functools.wraps(func)
		def Wrapper(*args, **kw):
			stime = time.clock()
			ret = func(*args, **kw)
			etime = time.clock()
			print '{0}: {1:,f}ms'.format(name, (etime-stime)*1000)
			return ret
		return Wrapper
	return Deco

@Timer('decorator test')
def Test():
	print 'hello, decorator'

Test()
なんてやればおっけー。
三重のdefとかあんまり使いたくないけどね・・・見づらい・・・。

ちなみに、内部的には
def Deco(func):
	def Wrapper(*args, **kw):
		print func.__name__
		return func(*args, **kw)
	return Wrapper

def Test():
	print 'a'
Test = Deco(Test)
ってやるのと同義みたいね。
引数付きの場合は
Test = Deco(u'引数')(Test)
ということになるみたい。

じゃあ@functools.wraps(func)は何かって? それが分からんのだよ。
省略すると、複数の関数をデコレーションした時におかしくなるんだけどね。後はよく分からん。
< メモリの中身と実行ファイル UnicodeとUCSとUTF >