在闭包的工作方式中遇到了一些奇怪的事情。考虑以下代码:
adders=[0,1,2,3]
for i in [0,1,2,3]:
adders[i]=lambda a: i+a
print adders[1](3)
它构建了一个简单的函数数组,这些函数接受单个输入并返回该输入加数字后的结果。这些函数在for
循环中构造,其中迭代器i
从0
到运行3
。对于这些数字中的每一个,lambda
都会创建一个函数i
,该函数捕获并添加到函数的输入中。最后一行使用参数作为参数调用第二个lambda
函数3
。令我惊讶的是6
。
我期望一个4
。我的推理是:在Python
中,所有东西都是对象,因此每个变量都是指向它的指针。为创建lambda
闭包时i,我希望它存储一个指向当前由指向的整数对象的指针i
。这意味着,当i
分配一个新的整数对象时,它不应影响先前创建的闭包。可悲的是,adders
在调试器中检查该阵列是否可以完成。所有的lambda
功能指的最后一个值i
,3
,其结果adders[1](3)
返回6
。
这让我想知道以下几点:
关于第一个问题:
闭包究竟捕获了什么?
Python的作用域是动态且词汇丰富的。闭包将始终记住变量的名称和范围,而不是其指向的对象。由于示例中的所有函数都是在相同的作用域中创建的,并且使用相同的变量名,因此它们始终引用相同的变量。
编辑:关于你如何解决此问题的另一个问题,有两种方法可以想到:
最简洁但并非严格等效的方法是Adrien Plisson推荐的方法。创建带有额外参数的lambda,并将额外参数的默认值设置为要保留的对象。
每次创建lambda时,创建一个新的作用域会更冗长一些,但hacky会更少一些:
>>> adders = [0,1,2,3]
>>> for i in [0,1,2,3]:
... adders[i] = (lambda b: lambda a: b + a)(i)
...
>>> adders[1](3)
4
>>> adders[2](3)
5
这里的范围是使用新函数(为简便起见,为lambda
)创建的,该函数绑定了其参数,并将要绑定的值作为参数传递。但是,在实际代码中,你很可能会使用普通函数而不是lambda
来创建新范围:
def createAdder(x):
return lambda y: y + x
adders = [createAdder(i) for i in range(4)]
闭包本身是相当灵活的,可以实现所需功能来让闭包运行而不用类型标注(原文:Closures are inherently flexible and will do what the functionality requires to make the closure work without annotation)。这允许变量捕获灵活地适应使用 情况,有时是移动(moving)有时是借用(borro
主要内容:Python闭包的__closure__属性前面章节中,已经对 Python 闭包做了初步的讲解,本节将详解介绍到底什么是闭包,以及使用闭包有哪些好处。 闭包,又称闭包函数或者闭合函数,其实和前面讲的嵌套函数类似,不同之处在于,闭包中外部函数返回的不是一个具体的值,而是一个函数。一般情况下,返回的函数会赋值给一个变量,这个变量可以在后面被继续执行调用。 例如,计算一个数的 n 次幂,用闭包可以写成下面的代码: 运行结果为: 4 8 在上面程
问题内容: 我已经在Python中看到并使用了嵌套函数,它们与闭包的定义匹配。那么为什么叫他们而不是? 嵌套函数不是因为外部世界不使用闭包吗? 更新:我正在阅读有关闭包的知识,这让我开始思考关于Python的这个概念。我搜索并找到某人在下面的评论中提到的文章,但是我无法完全理解该文章中的解释,所以这就是为什么我问这个问题。 问题答案: 当函数可以从完成其执行的封闭范围访问局部变量时,就会发生关闭。
闭包(closure)在 Rust 中也称为 lambda,是一类捕获封闭环境的函数。例如,一个可以捕获 x 变量的闭包如下: |val| val + x 它们的语法和能力使它们在临时(on the fly)使用相当方便。调用一个闭包和调用一个函数完全相同。然而,输入和返回类型两者都可以自动推导,且输入变量名必须指明。 其他的特点包括: 使用 || 替代 () 将输入变量括起来。 区块定界符({}
问题内容: 我已经在寻找我的答案几个小时了,但无法解决。请帮忙。 我想要做的是在Android中使用VpnService来抓取网络数据包,例如应用程序tPacketCapture 我首先使用了Google的ToyVpn示例代码并对其进行了修改,所以我不将数据发送到服务器。但是,我不确定这是否正确。 我的configure方法在调用build()之前将wlan ip地址用于binder.addAdd
对不起,我不知道这个问题的标题是什么。 我在C中有一个函数,它以λ作为参数。 然后我尝试调用这个函数。 我的问题是,我无法从lambda函数内部访问变量,如果我试图用