7月
14
2009
んで GitHub で公開。
http://github.com/holysugar/gae-amazon-proxy/tree/master
しかし作ってみた、のはいいがもういろいろ出てまわってるんだよなあ。:)
基本的にはただただしさんの amazon-auth-proxy の Python での GAE への移植。
たぶん、他の人のと似たようなバグがあるだろう。チェックしておかねばなあ。
最終目的は isbn anchor plugin 用の(透過でない) Proxy なんで、この Proxy を(おおっぴらに)公開はいまのところしてない。
今の仕事は Python を使ってがりがり書いてるせいか、特に Python で書くことに何の違和感もなくなってしまったなあ。何の制約もなければ Ruby やら Rails やらを使ってるんだけれども、 GAE 上で何かするなら Python でいいべ、と。これくらいのコードならすごく書きやすいし。
う、テスト書いてませんごめんなさい……(誰に謝ってるんだ)。
Tags: amazon, python
5月
07
2009
最近は仕事なんかで Python でコードを書くことが結構あるのだけど、知らずに惑ったことの一つに、関数のデフォルト引数が定義時にしか評価されない仕様というのがある。
デフォルトパラメタ値は関数定義を実行する際に値評価されます。 これは、デフォルトパラメタの式は関数を定義するときにただ一度だけ評価され、同じ”計算済みの”値が全ての呼び出しで使われることを意味します。
例えば無理矢理な例だけど、こんな風に使うことも可能。関数ローカルの変数扱いですな。
def fib(num, cache=[0,1]):
assert len(cache) > 1
if len(cache) > num:
return cache[num]
else:
cache[num:num] = [fib(num-1) + fib(num-2)]
return cache[num]
print fib(10) # => 55
試しに、この仕様に反して、 Python でも呼びだしの度にデフォルト引数が初期化されるようなコードを、デコレータを使って書いてみた。
デコレータというのは簡単に言うと関数に被せるラッパーを書くためのシンタックスシュガー。
def newdefaults(fn):
import copy
arity = fn.func_code.co_argcount
newdefaults.defaults = copy.deepcopy(fn.func_defaults)
def newfn(*args):
args = list(args)
while len(args) < arity:
index = len(args) - arity + len(newdefaults.defaults)
if index < 0: # 引数たりない
return fn(*args)
arg = newdefaults.defaults[index]
args.append(copy.deepcopy(arg))
return fn(*args)
return newfn
if __name__ == '__main__':
@newdefaults
def f(v1, v2, d=0, a=[0]):
print "f(%s, %s, %s, %s)" % (v1, v2, d, a)
a.append(v1)
return a
assert f(1,0) == [0,1]
assert f(2,0) == [0,2]
try:
f()
assert False
except TypeError, e:
print e # OK
except:
print "Unexpected error"
assert False
結果はこう。
f(1, 0, 0, [0])
f(2, 0, 0, [0])
f() takes at least 2 arguments (0 given)
*args および **kwargs を引数にとる関数には適用できないはず。
- ポイント: 関数の様子はある程度は function のプロパティ、
f.func_defaults や f.func_code などから分かる。もっと詳しく調べたいときは import inspect。
- deepcopy しちゃうとまずい時もありそうだけどまあいいか。
Tags: python