世の中には二種類の人間がいる。他人の食器を使っても平気な人間とそうでない人間だ。ああ、俺はもちろん後者だよ。
それはともかく、 io の現在のバージョンでは Importer が機能していない模様。 Importer clone で単なる Object が返されるので、これはガチかと。
ここ最近 Python で変なコードを書いて遊んでいたけど、あれは技術的には全然スマートじゃないかもしれない。例えばエセ型チェックなんてのはその典型で、そんなの最初っから静的型チェックをしてくれる言語使えよって話だ。確かにああいう処理が書けることは Python の強力さの一部ではあるし、使いでのある場面もあるのかもしれない。でもあんなことやってたって良いソフトウェアは書けないんじゃないか?
Python で関数型っぽいことをやるのは案外役に立ったけど、それはあくまでも関数型のパラダイムの一部を Python でも書ける (そして役に立つ) 範囲で翻案してるってだけで、別に Python がバリバリの関数型言語ってわけでは無いだろうし、第一そんなことを証明したいなんて全然思わない。第一この手の話は宗教論争の火種でしかないだろうし。
気がついたら手段と目的が逆転しているのは俺の悪い癖だ。時にはその方が都合がいいのかもしれない。でも、出来るだけ早く目を覚ましてもっとまともなソフトウェアを書くことに専念するべきだ。
uga-, 古いファイルが残っていたせいで動作がおかしくなってたのか。折角 Subversion 使ってるんだから、強気にファイルを削除するようにしようかな。
def groupbyhead(array, headsize=1):
d = {}
for i in array:
try:
d[i[0:headsize]].append(i)
except KeyError, e:
d[i[0:headsize]] = []
d[i[0:headsize]].append(i)
return d
こっちの方が良くないか。
メモ化は計算量を大幅に削減できるけれど、場合によってはメモリ不足を引き起こしてしまう。やはりガベージコレクタみたいなのが必要かもしれない。このことは Python Cookbook の Cache decorator in python 2.4 でも指摘がされているし、それを解決するためのもジュールもあるようだ (使ったことないけど)。
サイズのみによる制限以外の方法を極めて単純に考えれば、長く使われない値は多分二度と使われないと判断するってのがある。単純に引数と結果の辞書にせず、引数と結果、使われた回数や最終アクセス時刻でデータを保持しておき、ある一定の回数の呼出が行われた場合あまり使われていないデータを削除、といった所か?
因みに以下はやっつけで実装したガベージコレクタまがい付のメモ化関数。テスト実装ということで、単に値の使われた回数だけで判別。
def gc_memoize(f):
cache = {}
f.called = 0
def func(*args, **kwds):
f.called += 1
key = (str(args), str(kwds))
try:
r = cache[key][0]
except:
r = f(*args, **kwds)
cache[key] = [r, 0]
cache[key][1] += 1
if f.called >= 100:
d = []
for k, v in cache.iteritems():
if v[1] <= 1:
d.append(k)
for i in d:
del cache[i]
f.called = 0
return r
func.func_name = f.func_name
return func
当然ながらかなりパフォーマンスが悪くなったので、大人しく単純なサイズ制限をしておいた方が良いかも。そのサイズ制限機構の中でガベージコレクタっぽいものを実装するのがベストか?
ところで例の萌えタイトルジェネレータ、「キ」だけじゃなくて「イ」や「リ」でも面白い物が出来るんじゃないかと思ってやってみたらデータが 500MB をオーバーしたよ。主にサーバの容量という問題があるので、ちょっと CGI 版を公開するのは無理だな (home 領域が 2G しかないので。実の所前のバージョンでもちょっと厳しい)。
しかし、まさか自宅サーバで容量が問題になるとは。そういや、卒論のデモも容量が問題で大学のサーバで動かしてるんだった。