

定義を少しずつ変えた複数の関数を辞書形式で保持したいため、  
以下の様なpythonのコードを考えました。

[code]

    funcs = {}
    for i in range(5):
        new_key = 'f'+str(i+1)
        funcs[new_key] = lambda x: x**i  #0次関数から4次関数を格納
    
[/code]

しかしそれぞれの関数に引数を与えると、全て同じ値が返ってきます(最後に格納した関数の値)

[code]

    for f in funcs.values():
        print(f(5))
    
[/code]

実行結果：

[code]

    625
    625
    625
    625
    625
    
[/code]

これを(1, 5, 25, 125, 625)を返すようにしたいのですが、  
どのようにすればよいかご教授いただけないでしょうか。

ちなみに、for文を使わずに一つ一つ手で格納すると正しく値が返ってきました。  
また上コードにより格納された各関数のidは別々となっていました。

[code]

    for f in funcs.values():
        print(id(f))
    
[/code]

実行結果：

[code]

    4503380040
    4503310120
    4503309984
    4503309848
    4503309168
    
[/code]

以上、よろしくお願い致します。


CC BY-SA 3.0
2018-04-23T17:12:07.487
43502
2020-11-18T08:57:00.640
2018-04-24T04:10:32.560
28288
28288
question
python lambda
for文を用いてlambda関数を辞書に格納する方法

[code]

    funcs[new_key] = lambda x: x**i  #0次関数から4次関数を格納
    
[/code]

この行で、ラムダ関数が見ているiは、中身の値ではなく変数のiそのものです。for文の中では同じiが使いまわされるので、iが変更されれば、ラムダ関数が後でiを参照するときには、当然最新の値をとってくることになります。

解決方法の一例を挙げると

[code]

    funcs[new_key] = (lambda j: lambda x: x**j)(i)
    
[/code]

これはラムダ関数の引数の有効範囲は、そのラムダ関数の中だけであることを利用しています。`lambda j: lambda x:
x**j`はラムダ関数を返すラムダ関数ですが、jの有効範囲は、この行だけなので、この行に来るたびに新しいjが作られ、使いまわされることはありません。`(lambda
j: lambda x: x**j)(i)`で、iの値を実引数としてjにコピーすることで、funcsのラムダ関数が一つ一つが独自の値を持つことになります。


CC BY-SA 3.0
2018-04-23T22:12:21.100
43504
2018-04-23T22:12:21.100
3605
43502
answer


本家StackOverflow質問 [Python lambda's binding to local
values](https://stackoverflow.com/questions/10452770/) で紹介されてる別回答です。

ラムダ式のデフォルト引数を用いると、一部の値（ここでは`i`）をラムダ式による関数オブジェクト構築時点の値に束縛できます。

[code]

    funcs[new_key] = lambda x, i=i: x**i
    
[/code]


CC BY-SA 4.0
2020-11-18T08:57:00.640
72034
2020-11-18T08:57:00.640
49
43502
answer