2015-07-10 171 views
1

我使用scipy优化最小化包。为了为我的问题提供约束,我需要创建一个庞大的元组。我这样做以下列方式:python中lambda函数的列表参数

c0 = []; 
count = 0; 
for i in range(0, Nx): 
    for j in range(0, Ny): 
     c0.append({'type': 'eq', 'fun': lambda x: x[count]*x[count] + x[T + count]*x[T + count] + x[2*T + count]*x[2*T + count] - 1.}); 
     count+=1; 
cons = tuple(c0); 

但当极小需要他们来使用,总是需要的count终值,这显然会导致成index out of bounds错误。尝试del(count)导致了另一个错误,所以我想我的lambda函数用法的python方式的理解有问题。也许有更好的,使用切片和东西的python风格的方式?将不胜感激任何帮助。

+2

lambda中的名称将计算为lambda运行时名称的值,而不是创建时的值。这解释了您的终端计数问题。有关更多信息,请参见[Python嵌套函数中的局部变量](http://stackoverflow.com/q/12423614/953482)。 – Kevin

回答

4

变量中的count变量在您调用lambda函数时进行评估,而不是在创建它时(与其他语言不同)。你需要做的是迫使该变量的副本,一个办法可以使用闭包:

c0.append({ 
     'type': 'eq', 
     'fun': (lambda count: lambda x: x[count]*x[count] + x[T + count]*x[T + count] + x[2*T + count]*x[2*T + count] - 1.) (count) 
}); 

另一种方式(IMO取巧的办法)被作为一个参数的默认值使用方法:

c0.append({ 
    'type': 'eq', 
    'fun': lambda x, count = count: x[count]*x[count] + x[T + count]*x[T + count] + x[2*T + count]*x[2*T + count] - 1. 
}); 
+0

非常感谢您的快速响应!那正是我想要的! –

0

你在那里做的是创建一个函数对象,其中引用一个变量,它不创建自己的副本,所以当你去执行该函数时,它查找变量,它现在有循环中的最后一个值。

@Holt closure可能是完成任务的最安全的方法,尽管有点复杂。我会在闭包中更改变量的名称,以便更清楚地了解正在发生的事情。

这样做是创建一个单独的作用域,以便一旦执行离开外部lambda函数(调用它并返回一个值,它是您实际需要的函数对象)时,函数对象中的count变量和count变量在循环中不再引用内存中的相同位置,并且可以递增计数器而不影响该函数引用的变量。