zey*_*cus 2 python lambda list-comprehension
我不理解一段代码的行为,涉及一个在不同对象中调用方法的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])
Run Code Online (Sandbox Code Playgroud)
我得到的输出是[6.6, 6.6, 6.6],这意味着它是ev3一直被评估的方法.而不是[2.6, 4.6, 6.6]像我期望的那样.但令我惊讶的是,如果我摆脱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 = [ev.eval for ev in (ev1, ev2, ev3)]
print([f(0.5) for f in funcs])
Run Code Online (Sandbox Code Playgroud)
回报[2.5, 4.5, 6.5].谁能解释一下这里发生了什么?我应该如何以Pythoninstic方式编写代码?
问题是你在调用函数时只评估ev .因此,ev它只在您启动print语句时使用任何值.当然,到那个时候ev有列表中最后一个函数的值.
这与你做过这个没什么不同:
funcs = [lambda x: ev.eval(x+0.1),
lambda x: ev.eval(x+0.1),
lambda x: ev.eval(x+0.1)]
Run Code Online (Sandbox Code Playgroud)
请注意,它们是如何使用ev,他们都将使用相同 ev的运行功能的时间.
要做你想做的事,你需要ev在定义理解时绑定到列表理解中的当前值,你可以通过传递lambda参数来做到这一点:
funcs = [lambda x, ev=ev: ev.eval(x+0.1) for ev in (ev1, ev2, ev3)]
Run Code Online (Sandbox Code Playgroud)
但是,我强烈建议你不要这样做.正如您刚刚经历的那样,这样的代码很难理解和调试.你不会因为尽可能多的功能填充到一行而赢得任何积分.
技术术语是关闭.有关更多信息,请查看stackoverflow上的这个问题: 为什么不将python嵌套函数称为闭包?
| 归档时间: |
|
| 查看次数: |
146 次 |
| 最近记录: |