Pythonで「メモ化(Memoization)」の効いたプロパティがかんたんに作れる「memoize(メモワイズ)」
Python Package Index - memoize
https://pypi.python.org/pypi/memoize/
GitHub - sionide21 / memoize
https://github.com/sionide21/memoize
「memoize(メモワイズ)」は、Pythonで「メモ化(memoize / memoization)」の効いたプロパティがかんたんに作れるライブラリ。作者はBen Olive。
ウィキペディア - メモ化
http://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%A2%E5%8C%96
<メモ化(英: Memoization)とは、プログラムの高速化のための最適化技法の一種であり、サブルーチン呼び出しの結果を後で再利用するために保持し、そのサブルーチン(関数)の呼び出し毎の再計算を防ぐ手法である>。
「メモ化(Memoization)」とは、かんたんに言うと、計算結果を保持しておいて、同じ計算を2度やらないようにする手法である。
メモ化は有名な手法なので、各言語にライブラリがたくさんあるようで、Pythonにも同種のものがすでにけっこうある。この「memoize(メモワイズ)」も、特に目新しいものではないが、メモ化だけに特化しており、コードもきわめて小さく、わかりやすいので、紹介してみたい。
memoizeは、次のようにして使う(以下はページにのっているコード例)。
from memoize import mproperty
class Foo(object):
@mproperty
def bar(self):
return 2 * 2 * 2
メモ化したいメソッド(ここでは「bar」)に、このように「mproperty」というデコレータ(「@」からはじまる)をつけるだけだ。Python組み込みの(読み取り)プロパティ作成デコレータは「property」なので、その先頭に「m」をつけたものにしたのだろう。
「mproperty」デコレータをつけた(引数なしの)メソッドは、プロパティとしてアクセスできる。これはPython組み込みの「property」デコレータと同じである。異なるのは、「mproperty」はメモ化されたプロパティをつくってくれるので、メソッド内部の計算は、2回目からは呼ばれない、というところだ。
Python組み込みの「property」では、プロパティにアクセスされるたびに、そのメソッド内部の計算がおこなわれる。「mproperty」は、1回目に呼ばれたとき、その計算結果をオブジェクト上に保存しておき、2回目からはそのキャッシュを使う。これが「メモ化」の手法である。オブジェクトが生存している限り、そのキャッシュは有効なので、同じ計算が2回おこなわれることはない。
memoizeライブラリは、「memoize.py」というファイル1個だけでできている。その中身は、以下のようなものだ。
from functools import wraps
def mproperty(fn):
attribute = "_memo_%s" % fn.__name__
@property
@wraps(fn)
def _property(self):
if not hasattr(self, attribute):
setattr(self, attribute, fn(self))
return getattr(self, attribute)
return _property
たったこれだけである。
関数「mproperty」がデコレータで、「fn」がデコレータをつけるメソッド、「self」がインスタンスである。
ここでやっていることは、かんたんにいうと、元の「fn」メソッドをラップする「_property」という関数を作って、それを「fn」と置き換える、というものだ。「_property」の中では、インスタンス(self)の上に、fnの計算結果をキャッシュしておき、キャッシュがあるときはそれを使う、というふうにしている。
これくらいであれば、Pythonを多少勉強すれば、誰でも書ける。じっさい、ソフトウェア開発の現場では「メモ化」はしょっちゅう使われるので、このくらいのものは、いちいちライブラリを探したりせず、自分でサッサと書いてしまうのが普通だろう。
この「memoize」ライブラリがいいのは、そこをあえてライブラリにして、わざわざ公開しているところだろう。もちろん実用的にも使えるが、このたった数行の小さいコードが、Python初学者にはとても勉強になる。
「メモ化」はほんとうに、しょっちゅう使うので、Pythonの標準ライブラリに入っていてもおかしくないと思う。「mproperty」というのは、デコレータの表記としてもわかりやすいので、このまま標準ライブラリに入ってほしいくらいだ。
関連エントリ:
Pythonを始めるなら、1ファイルの軽量Webフレームワーク「Bottle」がおすすめ
http://mojix.org/2013/01/04/python-bottle
https://pypi.python.org/pypi/memoize/
GitHub - sionide21 / memoize
https://github.com/sionide21/memoize
「memoize(メモワイズ)」は、Pythonで「メモ化(memoize / memoization)」の効いたプロパティがかんたんに作れるライブラリ。作者はBen Olive。
ウィキペディア - メモ化
http://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%A2%E5%8C%96
<メモ化(英: Memoization)とは、プログラムの高速化のための最適化技法の一種であり、サブルーチン呼び出しの結果を後で再利用するために保持し、そのサブルーチン(関数)の呼び出し毎の再計算を防ぐ手法である>。
「メモ化(Memoization)」とは、かんたんに言うと、計算結果を保持しておいて、同じ計算を2度やらないようにする手法である。
メモ化は有名な手法なので、各言語にライブラリがたくさんあるようで、Pythonにも同種のものがすでにけっこうある。この「memoize(メモワイズ)」も、特に目新しいものではないが、メモ化だけに特化しており、コードもきわめて小さく、わかりやすいので、紹介してみたい。
memoizeは、次のようにして使う(以下はページにのっているコード例)。
from memoize import mproperty
class Foo(object):
@mproperty
def bar(self):
return 2 * 2 * 2
メモ化したいメソッド(ここでは「bar」)に、このように「mproperty」というデコレータ(「@」からはじまる)をつけるだけだ。Python組み込みの(読み取り)プロパティ作成デコレータは「property」なので、その先頭に「m」をつけたものにしたのだろう。
「mproperty」デコレータをつけた(引数なしの)メソッドは、プロパティとしてアクセスできる。これはPython組み込みの「property」デコレータと同じである。異なるのは、「mproperty」はメモ化されたプロパティをつくってくれるので、メソッド内部の計算は、2回目からは呼ばれない、というところだ。
Python組み込みの「property」では、プロパティにアクセスされるたびに、そのメソッド内部の計算がおこなわれる。「mproperty」は、1回目に呼ばれたとき、その計算結果をオブジェクト上に保存しておき、2回目からはそのキャッシュを使う。これが「メモ化」の手法である。オブジェクトが生存している限り、そのキャッシュは有効なので、同じ計算が2回おこなわれることはない。
memoizeライブラリは、「memoize.py」というファイル1個だけでできている。その中身は、以下のようなものだ。
from functools import wraps
def mproperty(fn):
attribute = "_memo_%s" % fn.__name__
@property
@wraps(fn)
def _property(self):
if not hasattr(self, attribute):
setattr(self, attribute, fn(self))
return getattr(self, attribute)
return _property
たったこれだけである。
関数「mproperty」がデコレータで、「fn」がデコレータをつけるメソッド、「self」がインスタンスである。
ここでやっていることは、かんたんにいうと、元の「fn」メソッドをラップする「_property」という関数を作って、それを「fn」と置き換える、というものだ。「_property」の中では、インスタンス(self)の上に、fnの計算結果をキャッシュしておき、キャッシュがあるときはそれを使う、というふうにしている。
これくらいであれば、Pythonを多少勉強すれば、誰でも書ける。じっさい、ソフトウェア開発の現場では「メモ化」はしょっちゅう使われるので、このくらいのものは、いちいちライブラリを探したりせず、自分でサッサと書いてしまうのが普通だろう。
この「memoize」ライブラリがいいのは、そこをあえてライブラリにして、わざわざ公開しているところだろう。もちろん実用的にも使えるが、このたった数行の小さいコードが、Python初学者にはとても勉強になる。
「メモ化」はほんとうに、しょっちゅう使うので、Pythonの標準ライブラリに入っていてもおかしくないと思う。「mproperty」というのは、デコレータの表記としてもわかりやすいので、このまま標準ライブラリに入ってほしいくらいだ。
関連エントリ:
Pythonを始めるなら、1ファイルの軽量Webフレームワーク「Bottle」がおすすめ
http://mojix.org/2013/01/04/python-bottle