在python中构建参数化函数的动态列表

时间:2016-04-27 15:40:04

标签: python lambda

使用fmin_slsqp,我必须提供

ieqcons : list, optional

A list of functions of length n such that ieqcons[j](x,*args) >= 0.0 in a successfully optimized problem.

由于我的问题很大,明确编写它们的简单选项不起作用。

def f1(x,arg1,arg2):
     ...
def f2(x,arg1,arg2):
     ...
...

list_func = [f1,f2,...]

这个问题解决了dynamic and anonymous functions in Python,大部分答案都是将代码解析为字符串,这似乎完全没必要,并且使参数传递给函数变得复杂。

约束列表的本质是单个参数(例如索引)可以唯一地标识函数,但列表中的所有函数都接收相同的参数,并且不可能基于传递的参数进行区分。 / p>

这种形式的构造足够且无痛

def f(x,arg1,arg2,i):
   # return value based on i
   # e.g. # for constrain of form x[i]>=arg1[i] the funct is:
   #        return x[i]-arg1[i]

i = 1
f1 = lambda x,arg1,arg2 : f(x,arg1,arg2,i)
i = 2
f2 = lambda x,arg1,arg2 : f(x,arg1,arg2,i)

致电f1f2会返回i=2的相同功能

但是我找不到在函数定义中使i成为最终的解决方案,或者限制其范围,对特定lambda函数的可见性。

作为评论,i必须保持变量,因为最终解决方案看起来像

list_f =[]
for i in range(0,num_cons):
    list_f.append(lambda x,arg1,arg2 : f(x,arg1,arg2,i))

我如何解决这个问题,或者是否有更简单明智的方法来实现我的目标?

3 个答案:

答案 0 :(得分:2)

据我了解,您可以使用functools.partial解决问题:

def startingNode(self,destID,message,counter):
    pack =  self.pac.packet(self.name,destID,message)
    switch1Flow = []
    switch2Flow = []
    switch3Flow = []
    if counter == "0":
        nextHop = self.controller.selectSwitch(self.name)
        print "Switch",self.name,"contacts controller"
        nextHop.receivePacket(pack)
        switch1Flow = [nextHop.name] //list1
        print switch1Flow
        nextHop1 = self.controller.selectSwitch(nextHop.name)
        print "Switch",nextHop.name,"contacts controller"
        nextHop1.receivePacket(pack)
        nextHop2 = self.controller.selectSwitch(nextHop1.name)
        print "Switch",nextHop1.name,"contacts controller"
        nextHop2.receivePacket(pack)
        switch2Flow = [self.name,nextHop1.name] //list2
        print switch2Flow
        switch3Flow = [nextHop.name,nextHop2.name] //list3
        print switch3Flow
    elif counter == "1":
        if 's2' in switch1Flow:
           print "forwarding to s2"
           if 's1' in switch2Flow and 's3' in switch2Flow:
             print "forwarding to s3"
             if 's2' in switch3Flow and 's4' in switch3Flow:
                 print "forwarding to s4"
                 print "message reched s4"

您可以在此处找到有关typedef struct StackNode *StackNodePtr; vs from functools import partial list_f = [partial(f, i=i) for i in range(0, num_cons)] 的更多信息:

答案 1 :(得分:1)

它没有按预期工作的原因是当你写一个lambda表达式时,它不会调用该函数;在评估表达式时调用它。

因此,当您评估它时,i的值为2,因此结果相同。

我相信你所需要的是functools.partial,就像这样:

from functools import partial

func_call_map = {i: partial(f, i=i) for i in [some range]}

# Get result for i = 4
ret_value = func_call_map[4](other, args, here)

答案 2 :(得分:1)

关注Python: Why is functools.partial necessary?上的@alecxe链接以及其中一个答案的评论中提供的解释,为避免@BurhanKhalid解释的后期绑定(延迟评估),代码需要更改如下< / p>

if ($stmt = $conn->prepare("INSERT INTO `game`.`login_data` (username, password) VALUES (?, ?)")) {
        $stmt->bind_param('ss', $username , $password );
        // Execute the prepared query.
        if (! $stmt->execute()) {
            $stmt->close();
        }
    }
}

但使用i = 1 f1 = lambda x,arg1,arg2,n_i=i : f(x,arg1,arg2,n_i) i = 2 f2 = lambda x,arg1,arg2,n_i=i : f(x,arg1,arg2,n_i) 可提供更优雅的解决方案。