6

今日、私は Pythonの奇妙な動作について調べました。例:

closures = []
for x in [1, 2, 3]:
    # store `x' in a "new" local variable
    var = x

    # store a closure which returns the value of `var'
    closures.append(lambda: var)

for c in closures:
    print(c())

上記のコードが出力されます

3
3
3

でも印刷したい

1
2
3

常に同じローカル変数であるこの動作を自分で説明しvarます (そして、python は他の言語のように新しい変数を作成しません)。各クロージャーが別の値を返すように、上記のコードを修正するにはどうすればよいですか?

4

3 に答える 3

11

これを行う最も簡単な方法は、ラムダにデフォルトの引数を使用することです。この方法では、呼び出しごとに包含スコープで検索されるxのではなく、現在の値が関数のデフォルト引数としてバインドされます。var

closures = []
for x in [1, 2, 3]:
    closures.append(lambda var=x: var)

for c in closures:
    print(c())

または、クロージャーを作成することもできます (各関数はグローバル スコープで作成されるため、クロージャーではありません)。

make_closure = lambda var: lambda: var
closures = []
for x in [1, 2, 3]:
    closures.append(make_closure(x))

for c in closures:
    print(c())

make_closure()次のように書くこともできます。これにより、読みやすくなります。

def make_closure(var):
    return lambda: var
于 2012-07-06T16:50:00.813 に答える
6

ループ内のローカル スコープで新しい変数を作成することはできません。どのような名前を選択しても、関数は常にその名前のクロージャーであり、最新の値を使用します。

これを回避する最も簡単な方法は、キーワード引数を使用することです。

closures = []
for x in [1, 2, 3]:
    closures.append(lambda var=x: var)
于 2012-07-06T16:49:01.157 に答える
1

あなたの例では、varは常にループの最後の値にバインドされています。を使用してラムダ内でバインドする必要がありますclosures.append(lambda var=var: var)

于 2012-07-06T16:51:51.353 に答える