我有一个函数元组,我想用一些数据预加载。目前我这样做的方式如下。本质上,我列出了一个新函数的列表,每次添加一个lambda函数,然后重新转换为一个元组。但是,当我在代码的不同部分使用这些函数时,它们中的每一个都会像是列表中的最后一个。在
def newfuncs(data, funcs):
newfuncs = []
for f in funcs:
newf = lambda x: f(x, data)
newfuncs.append(newf)
return tuple(newfuncs)
下面是这个问题的一个简单例子
^{pr2}$我希望数字15打印出来,然后是-5。但是,这段代码将数字-5打印两次。如果有人能帮助我理解为什么会发生这种事,我将不胜感激。谢谢!在
如前所述,问题在于变量
f
,它是分配给所有lambda
函数的同一个变量,因此在循环的末尾,每个lambda
看到的是相同的f
。在这里的解决方案是使用
functools.partial
,或者为lambda
创建一个限定范围的默认参数:像以前一样调用这些
^{pr2}$lambda
现在可以得到:如果您使用的是python3.x,请确保将此comment by ShadowRanger作为作用域默认参数方法的一个可能的安全特性。
这是一个众所周知的Python“问题”,或者我应该说“Python就是这样的”
您创建了元组:
但是
f
是什么?f
在您最后调用函数之前不会求值!在首先,}。然后在
f
是{for
-循环中,f
被重新分配给(x, y)=>x-y
。在当您终于开始调用函数时,那么,而且只有这样,才会查找
f
的值。此时f
的值是多少?所有函数的值都是(x, y)=>x-y
。你所有的函数都做减法。这是因为f
被重新分配。只有一个f
。在调用任何lambda之前,将该函数的值设置为减法函数。在附录
如果有人感兴趣,不同的语言以不同的方式处理这个问题。JavaScript在这里很有意思(有些人会说它令人困惑),因为它以Python的方式进行操作,这是OP意外的,而且是OP所期望的另一种方式。在JavaScript中:
^{pr2}$但是,如果您将上面的
let
更改为var
,它的行为类似于Python,并且两者都得到-5!这是因为使用let
,for循环的每次迭代都会得到不同的f
;使用var
,整个函数共享相同的f
,它会不断被重新分配。这就是Python的工作原理。在cᴏʟᴅsᴘᴇᴅ已经向您展示了实现您期望的方法是确保每次迭代都得到不同的
f
,Python允许您以非常简洁的方式来做,将lambda的第二个参数默认为该迭代的本地f
。这很酷,所以如果他们的回答对你有帮助的话,你应该接受。在相关问题 更多 >
编程相关推荐