1

脳を傷つける何かに出くわしました。次のことを考慮してください

fs = []
for i in range(3):
    fs.append(lambda : normal(i, .001))
    print mean([fs[-1]() for j in range(1000)])
print [mean([fs[i]() for j in range(1000)]) for i in range(3)]

たとえば、

-1.38651717873e-05                                                                                                                    |
1.00003545604                                                                                                                         |
1.99999343229                                                                                                                         |
[2.0530899455777235e-05, 0.99995283932453838, 2.0000045292311737] 

予想通り。今、物事を少し変更します

fs = []
for i in range(3):
    mu = i
    fs.append(lambda : normal(mu, .001))
    print mean([fs[-1]() for j in range(1000)])
print [mean([fs[i]() for j in range(1000)]) for i in range(3)]

そして、私たちは得る

5.56620751611e-06                                                                                                                     |
0.999999076252                                                                                                                        |
1.99995161119                                                                                                                         |
[2.0000016397219098, 1.9999853403014964, 2.0000209870831158] 

つまり、ループの外側にあるものごとに 2 つです。私の脳を混乱させた後、Python での参照/スコープは悪であることを思い出しました。答えは、通常に渡された mu が値ではなく参照によって格納されていることのようです (通常の言語では mu はスコープアウトする必要があります)。 . それが起こっていることですか?将来のコーディングで同様の狂気を避けるにはどうすればよいですか?

4

1 に答える 1

1

Python のクロージャは名前によるものです (厳密にはそうではありませんが、そのように考えることができます)。したがって、すべてのラムダは2forの値を持ちます。これは、ループ内で にmu与えられる最後の値だからです。関数定義時にmuの値を修正するには、次のようにデフォルトの引数値を使用します。mu

lambda mu=mu: normal(mu, .001)

(スコープ ルールは、実際にはこれとは何の関係もありません。)

于 2013-06-26T19:54:45.283 に答える