灵感来自:
http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/
长话短说, 先看代码.
>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13
不觉得该是
3 + 4 = 7
么?
>>> [f(4) for f in fs]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]
.....撞石头上了...
换
def
看:
>>> fs = []
>>> for i in range(10):
... def f(n): return i+n
... fs.append(f)
...
>>> [f(4) for f in fs]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]
其实这时候已经有点眉目了, 继续看下去:
>>> fs = []
>>> for i in range(10):
... def f(n, i=i): return i+n
... fs.append(f)
...
>>> [f(4) for f in fs]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
作者提到 Haskell 是没问题的:
Prelude> let fs = [(\n -> i + n) | i <- [0..9]]
Prelude> [f(4) | f <- fs]
[4,5,6,7,8,9,10,11,12,13]
想也是~ Haskell 就是做这个的.
怎么回事呢?
我觉得是 lexical scope(static scope) 和 dynamic scope 的关系.
lisp 中一般都会讲到这个.
在 def 使用时就已经可以看出, i 在这里作为全局变量了(或者说是上一级变量), 而调用的时候使用的是当前全局环境中的 i. 而 def f(n, i=i) 中, 局部 i 覆盖了全局的 i, 那么也就是说,
def 参数列表中默认值参数在定义后就已经绑定.
没有评论:
发表评论