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。在 kerploding 我的大脑之后,我记得 python 中的引用/范围是邪恶的,看起来答案是传递给 normal 的 mu 是通过引用而不是值存储的(即使 mu 应该用普通语言进行范围界定) . 这就是正在发生的事情吗?如何在未来的编码中避免类似的疯狂?

4

1 回答 1

1

Python 中的闭包是按名称命名的(好吧,从技术上讲不是,但你可以这样想它们)。因此,每个 lambda 都有一个值2for mu,因为这是mu循环中给定的最后一个值。要在函数定义时修复 的值mu,只需使用默认参数值,如下所示:

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

(范围规则与此没有任何关系。)

于 2013-06-26T19:54:45.283 回答