1. ホーム
  2. python

[解決済み] Python lambdaのローカル値へのバインディング

2023-05-19 12:25:21

質問

次のコードは 1 を2回出力していますが、私が期待するのは 0 と表示され、次に 1 .

def pv(v) :
  print v

x = []
for v in range(2):
  x.append(lambda : pv(v))

for xx in x:
  xx()

私は、pythonのラムダが、舞台裏で、ローカル変数が指す参照にバインドすることを期待していました。しかし、それは事実ではないようです。私は、ラムダがモダンC++のバインド('boost::bind' など)に相当することを行っている大規模なシステムでこの問題に遭遇しました。

では、ローカル変数をラムダ関数にバインドして、使用時に正しい参照を保持させるにはどうしたらよいのでしょうか。ガベージコレクタを持つ言語からこれを期待しないので、私はこの動作にかなり驚かされました。

どのように解決するのですか?

変更 x.append(lambda : pv(v))x.append(lambda v=v: pv(v)) .

Pythonのラムダは、ローカル変数が指している参照に裏でバインドしていると思うかもしれませんが、それはPythonの仕組みではありません。 Pythonは関数が呼び出されたときに変数名を調べますが、関数が作られたときには調べません。 デフォルトの引数は、関数が呼び出されたときではなく、関数が作成されたときに評価されるため、デフォルトの引数を使用すると動作します。

これはラムダについて特別なことではありません。 考えてみてください。

x = "before foo defined"
def foo():
    print x
x = "after foo was defined"
foo()

プリント

after foo was defined