最近我开始玩Python,我遇到了一些特殊的闭包方式.请考虑以下代码:
adders=[0,1,2,3]
for i in [0,1,2,3]:
adders[i]=lambda a: i+a
print adders[1](3)
Run Code Online (Sandbox Code Playgroud)
它构建了一个简单的函数数组,它接受单个输入并返回由数字添加的输入.函数在for循环中构造,迭代器i从中循环0到3.对于这些数字中的每一个,lambda都会创建一个函数i,该函数捕获并将其添加到函数的输入中.最后一行将第二个lambda函数3作为参数调用.令我惊讶的是输出结果是6.
我期待一个4.我的理由是:在Python中,一切都是一个对象,因此每个变量都是指向它的指针.在创建lambda闭包时i,我希望它存储一个指向当前指向的整数对象的指针i.这意味着当i分配一个新的整数对象时,它不应该影响先前创建的闭包.遗憾的是,adders在调试器中检查数组表明它确实存在.所有的lambda功能指的最后一个值i,3,这将导致adders[1](3)返回6.
这让我想知道以下内容:
lambda函数以更改其值i时不会受到影响的方式捕获当前i值?如何将参数绑定到Python方法以存储一个用于以后调用的nullary仿函数?与C++类似boost::bind.
例如:
def add(x, y):
return x + y
add_5 = magic_function(add, 5)
assert add_5(3) == 8
Run Code Online (Sandbox Code Playgroud) 以下代码吐出1两次,我期望看到0然后1
def pv(v) :
print v
def test() :
value = []
value.append(0)
value.append(1)
x=[]
for v in value :
x.append(lambda : pv(v))
return x
x = test()
for xx in x:
xx()
Run Code Online (Sandbox Code Playgroud)
我希望python lambdas绑定到一个局部变量指向的引用,在场景后面.然而,情况似乎并非如此.我已经在一个大型系统中遇到了这个问题,其中lambda正在做现代C++的一个绑定的等价物(例如'boost :: bind'),在这种情况下,你将绑定到智能ptr或复制contstruct lambda的副本.
那么,如何将局部变量绑定到lambda函数并在使用时保留正确的引用?我对这种行为非常惊讶,因为我不希望这种语言来自垃圾收集器.
有问题的代码如下所示(l3_e是导致问题的变量):
for category in cat :
for l2 in cat[category].entries :
for l3 in cat[category].entries[l2].entry["sub_entries"] :
l3_e = cat[category].entries[l2].entry["sub_entries"][l3]
url = "http://forums.heroesofnewerth.com/" + l3_e.entry["url"]
self.l4_processing_status[l3_e] = 0
l3_discovery_requests.append( Request(
url, callback = lambda response : self.parse_l4(response,l3_e))) …Run Code Online (Sandbox Code Playgroud)