SSブログ

Python のデフォルト引数に辞書を使う件 [Python]

http://d.hatena.ne.jp/kwatch/20080415/1208274736
def f(d={}) という定義があった場合、Ruby では「{}」が関数呼び出しごとに評価されるので、関数呼び出しごとに新しい Hash オブジェクトが生成される。 これに対し、Python では「{}」が定義時にしか評価されないので、dict オブジェクトは定義時に 1 回だけ生成され、それが毎回引数として渡される。

これについては個人的には関数のキャッシュの置き場所としてわりと重宝してるのでこのままでいいかなあと思う。
こんな風なコードの書き換えを良くする。
def fib1(n):
  if n <= 2:
    return 1
  else:
    return fib1(n-2)+fib1(n-1)

def fib2(n, cache={}):
  if cache.has_key(n):
    return cache[n]
  if n <= 2:
    return 1
  else:
    cache[n] = fib2(n-2)+fib2(n-1)
    return cache[n]

スコープ的にグローバルというわけではなく、それでいて関数呼び出しをまたいで寿命があるオブジェクトが作れるので割りとうまい具合に収まります。まあなんか泥臭い気がするよ?といわれればそうかもしれないのですが。
Python で関数の戻り値をキャッシュするときの手軽なイディオムが他にあれば知りたいところです。

古い Python の変数のスコープ [Python]

今日 Jython 2.1 を使っていてラムダの自由変数ではまった。短く表現すると以下のような感じのコード。

(lambda x: lambda y: x + y)(2)(3)

5を返してほしいんだけどこれは NameError: x となる。つまり内側の lambda から外の x が見えない。こういう仕様だというのに今まで気づかなかった。以下のようにすると回避できる。

(lambda x: lambda y, x=x: x + y)(2)(3)

あたらしめの Python では最初の例が期待通りに動く。少なくとも 2.4 では動いた。しかし CPython が最新 2.5 のところを Jython が開発版でもまだ 2.2 というのはさびしいなあ。


この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。