在 Lambdas 中捕获值而不是引用
Capturing Value instead of Reference in Lambdas
Eli Bendersky (http://eli.thegreenplace.net/2015/the-scope-of-index-variables-in-pythons-for-loops/)
给出的这个例子让我有点吃惊
>>> def foo():
... lst = []
... for i in range(4):
... lst.append(lambda: i)
... print([f() for f in lst])
...
>>> foo()
[3, 3, 3, 3]
但是当我考虑它时,它是有道理的 — lambda 正在捕获对 i 的引用而不是 i 的值。
所以解决这个问题的方法如下:
>>> def foo():
... lst = []
... for i in range(4):
... lst.append((lambda a: lambda: a)(i))
... print([f() for f in lst])
...
>>> foo()
[0, 1, 2, 3]
这似乎有效的原因是当 i 被提供给外部 lambda 时,外部 lambda 创建一个范围并取消引用 i,将 a 设置为 i。然后,返回的内部 lambda 包含对 a.
的引用
这个解释正确吗?
是的,看起来是正确的。如果您熟悉 javascript 并知道闭包,您会注意到它们有多么相似。
如果不是 - 有一个很好的 explanation on SO regarding JS closures 并且概念完全相同(以及解释,甚至错误和正确的用法)。
默认参数是获取值的另一种方式:
lst.append(lambda i=i: i)
It appears that the reason that this works is that when i is provided
to the outer lambda, the outer lambda creates a scope and dereferences
i, setting a to i. Then, the inner lambda, which is returned, holds a
reference to a.
Is this a correct explanation?
我不喜欢。 Python 不通过引用:
def func(x):
x = 10
num = 3
func(num)
print num #=>3
因此,术语 reference 和 dereference 不在 python 词典中。或者,您可以说 python 总是 在将函数参数分配给参数变量之前取消引用函数参数——所以您的解释并没有真正解释任何东西。
示例之所以有效是因为规则:
A function's local variables are destroyed after it finishes executing.
函数的局部变量包括它的参数变量。每次执行外部 lambda 时,都会创建一个新的 'a' 变量。结果,每个内部 lambda 关闭不同的 'a' 变量。
你确实提到了那种情况:
the outer lambda creates a scope
...
the lambda is capturing a reference to i rather than i's value.
或者,正如我喜欢的说法。
A closure closes over variables--not values.
这就是大多数语言中闭包的工作方式(perl 是一个例外,闭包关闭值)。
Eli Bendersky (http://eli.thegreenplace.net/2015/the-scope-of-index-variables-in-pythons-for-loops/)
给出的这个例子让我有点吃惊>>> def foo():
... lst = []
... for i in range(4):
... lst.append(lambda: i)
... print([f() for f in lst])
...
>>> foo()
[3, 3, 3, 3]
但是当我考虑它时,它是有道理的 — lambda 正在捕获对 i 的引用而不是 i 的值。
所以解决这个问题的方法如下:
>>> def foo():
... lst = []
... for i in range(4):
... lst.append((lambda a: lambda: a)(i))
... print([f() for f in lst])
...
>>> foo()
[0, 1, 2, 3]
这似乎有效的原因是当 i 被提供给外部 lambda 时,外部 lambda 创建一个范围并取消引用 i,将 a 设置为 i。然后,返回的内部 lambda 包含对 a.
的引用这个解释正确吗?
是的,看起来是正确的。如果您熟悉 javascript 并知道闭包,您会注意到它们有多么相似。
如果不是 - 有一个很好的 explanation on SO regarding JS closures 并且概念完全相同(以及解释,甚至错误和正确的用法)。
默认参数是获取值的另一种方式:
lst.append(lambda i=i: i)
It appears that the reason that this works is that when i is provided to the outer lambda, the outer lambda creates a scope and dereferences i, setting a to i. Then, the inner lambda, which is returned, holds a reference to a.
Is this a correct explanation?
我不喜欢。 Python 不通过引用:
def func(x):
x = 10
num = 3
func(num)
print num #=>3
因此,术语 reference 和 dereference 不在 python 词典中。或者,您可以说 python 总是 在将函数参数分配给参数变量之前取消引用函数参数——所以您的解释并没有真正解释任何东西。
示例之所以有效是因为规则:
A function's local variables are destroyed after it finishes executing.
函数的局部变量包括它的参数变量。每次执行外部 lambda 时,都会创建一个新的 'a' 变量。结果,每个内部 lambda 关闭不同的 'a' 变量。
你确实提到了那种情况:
the outer lambda creates a scope
...
the lambda is capturing a reference to i rather than i's value.
或者,正如我喜欢的说法。
A closure closes over variables--not values.
这就是大多数语言中闭包的工作方式(perl 是一个例外,闭包关闭值)。