我不理解一个包含不同对象行为的lambda函数。它发生在一个大型项目中,所以对于这个问题,我制作了一个毫无意义的玩具箱来说明我的观点:
class Evaluator(object):
def __init__(self, lft, rgt):
self.lft = lft
self.rgt = rgt
def eval(self, x):
return self.lft + x * (self.rgt - self.lft)
if __name__ == "__main__":
ev1 = Evaluator(2, 3)
ev2 = Evaluator(4, 5)
ev3 = Evaluator(6, 7)
funcs = [lambda x:ev.eval(x+0.1) for ev in (ev1, ev2, ev3)]
print([f(0.5) for f in funcs])
我得到的输出是[6.6, 6.6, 6.6]
,这意味着它是ev3
中一直被计算的方法。而不是[2.6, 4.6, 6.6]
,正如我所料。但真正让我吃惊的是,如果我去掉lambda函数,它的行为是好的:
返回[2.5, 4.5, 6.5]
。有人能解释一下这是怎么回事吗?我应该如何用python的方式来编码呢?在
问题是,您只在调用函数时计算ev。因此,它只在启动print语句时使用
ev
的任何值。当然,到那时,ev
已经有了列表中最后一个函数的值。在这和你这样做没有什么不同:
注意它们是如何使用
ev
,并且在您运行这些函数时,它们都将使用相同的相同的ev
。在要想做什么,您需要在定义理解时将
^{pr2}$ev
绑定到列表理解中的当前值,您可以通过lambda参数传递值来实现:但是,我强烈建议你这样做。正如您刚刚经历的,这样的代码很难理解和调试。在一行代码中尽可能多地使用功能是没有好处的。在
技术术语是闭包。有关详细信息,请查看stackoverflow上的以下问题: Why aren't python nested functions called closures?
问题在于lambdas的计算方式。这三只羔羊都是这样的:
但是在理解之后,
ev
的值是ev3
,因此这三个lambda都是相同的。在可以通过在计算函数之前删除
ev
来观察这一点。您将得到一个属性错误。在Why aren't python nested functions called closures?
{cddas>使用的lambdas来自于范围^ 1。执行lambda时,
ev
被绑定到ev3
。在注意:
这里,
^{pr2}$ev
是在lambda的创建时计算的:相关问题 更多 >
编程相关推荐