我以为我理解lambda符号(在python中)来定义函数,但是我看到了一个奇怪的行为,我不明白。我看了看What do (lambda) function closures capture?,看到了一些我认为相关但不相同的东西。你知道吗
我在一个函数中生成一个函数列表。在该函数中,列表中函数的行为与预期一样。但是,当它返回到main()时,列表中的项1到3的行为都与项3相同。我之所以说“behave as”,是因为可以看到函数实际上并不完全相同——它们存储在不同的内存位置。你知道吗
我放入了一些注释过的调试行,这有助于了解代码在做什么。lambda函数依赖于一个整数,该整数的值与函数中预期的值相同,但对于main()中的列表项1到3是相同的。你知道吗
如果有人能帮我了解这里的情况,我会非常感激的。谢谢!你知道吗
import numpy as np
def make_func_list(matA):
size = matA.shape[0]
vec = np.ones(size)
lst_f = []
lst_f.append( lambda x: sum(x) )
for ii in xrange(1,size):
lst_f.append( lambda x: np.dot(matA[ii], x) )
print '-----------------'
print '- in function -'
for ii in xrange(size):
print 'func_list', ii, lst_f[ii](vec)
print lst_f[ii] # note that the memory addresses are different
if ii > 0:
print lst_f[ii].func_closure[0].cell_contents # the integer is different
print '-----------------'
return lst_f
if __name__ == "__main__":
size = 4
matA = np.reshape(np.arange(size**2),(size,size))
vec = np.ones(size)
print "### matA ###"
print matA
func_list = make_func_list(matA)
print '================='
print '= in main() ='
for ii in xrange(len(matA)):
print 'func_list', ii, func_list[ii](vec)
print func_list[ii] # memory addresses are unchanged from in make_func_list()
if ii > 0:
print func_list[ii].func_closure[0].cell_contents # but the integer is the same for all ii
print '================='
在这些行中:
创建的lambda对象存储对
matA
和ii
变量的引用,当执行lambda时,它使用matA
和ii
在调用lambda时(而不是创建lambda时)具有的值来计算np.dot(matA[ii], x)
。不幸的是,lambda是在for
循环运行完毕后调用的,此时ii
的值将是最后一个赋值给它的值(即size-1
),因此所有lambda的行为方式都将是只期望最后一个lambda的行为方式。你知道吗有几种方法可以解决这个问题。一种方法是将
ii
的当前值存储在只有当前lambda可以访问的范围内,这可以通过创建并立即调用围绕“main”lambda的另一个lambda来完成:每次通过循环,
lambda
表达式都会创建一个function对象,其中包含对ii
的引用,当调用函数时,将查找该引用的值。因为所有的lambda
都在同一个范围内求值,所以它们都包含对同一名称ii
的引用。分配给该名称的最后一个值来自循环的最后一次迭代,因此尽管函数对象是在循环的不同迭代中创建的,但是每个函数对象在ii
中看到的值是相同的,即从xrange(size)
获得的最后一个值。你知道吗避免这种情况的一种简单(但有点尴尬)方法是将值
ii
作为参数的默认值传递给函数对象,因为默认值是在定义时计算的,而不是在调用时。你知道吗相关问题 更多 >
编程相关推荐