更改函数列表时出现意外结果(lambda)[重复]

Posted

技术标签:

【中文标题】更改函数列表时出现意外结果(lambda)[重复]【英文标题】:Unexpected result when changing list of functions (lambda) [duplicate] 【发布时间】:2021-03-06 03:41:30 【问题描述】:

我有一个函数列表,每个函数都有一个参数。

我想使用一个库的函数,它接受函数但希望它们没有参数。

所以我想创建一个新函数列表,使用 lambda 来“外部”传递参数

但是新的函数列表并没有产生预期的结果。

(这是一些最小的例子)

def fun_a(param):
    print("a")
    
def fun_b(param):
    print("b")
    

def do_something(funs):
    funs_out = []
    for fun in funs:
        funs_out.append(lambda: fun(0))
        
    return funs_out
        
   
funs = [fun_a,fun_b]

funs[0](0) # prints a
funs[1](0) # prints b

funs_changed = do_something(funs)
#funs_changed = [lambda: f(0) for f in funs]
    
funs_changed[0]() # prints b ??? expected a
funs_changed[1]() # prints b

我之前尝试过funs_changed = [lambda: f(0) for f in funs],因为它看起来更像pythonic,然后尝试使用更明确的代码(原始for循环)来查找根本原因,但没有成功。

我错过了什么?

【问题讨论】:

【参考方案1】:

你可以使用 functools.partial:

from functools import partial


def fun_a(param):
    print("a")
    
def fun_b(param):
    print("b")
    

def do_something(funs):
    funs_out = []
    for fun in funs:
        funs_out.append(partial(fun, 0))
        
    return funs_out
        
   
funs = [fun_a, fun_b]

funs[0](0)   # prints a
funs[1](0)   # prints b

funs_changed = do_something(funs)
# funs_changed = [partial(fun, 0) for f in funs]
    
funs_changed[0]() # prints a
funs_changed[1]() # prints b

来自this answer:

大致来说,partial 会做这样的事情(除了关键字 args 支持等):

def partial(func, *part_args):
    def wrapper(*extra_args):
        args = list(part_args)
        args.extend(extra_args)
        return func(*args)

    return wrapper

【讨论】:

它没有解释为什么问题中的例子不起作用? 您能就@Jocker 的回答发表声明吗?我应该使用哪种解决方案,哪个更容易理解/更 Pythonic? 对于这个用例,我发现functools.partiallambda 更容易理解,正如您发现的那样,要确定它有点棘手。当您阅读其他人的代码时尤其如此。在许多其他情况下,lambdas 非常好......但这只是我的意见,也许其他人会不同意。【参考方案2】:

只需使用价值破解:

funs_changed = [lambda f=f: f(0) for f in funs]

没关系并产生以下输出:

a
b
a
b

对于您的代码的初始变体还有一个解决方案:如果您希望将 do_something 函数保留为函数以避免主代码上下文中的内联 lamda-list 理解,只需修补 do_something 函数(我们将在函数中进行):

def do_something(funs):
    funs_out = [lambda f=f: f(0) for f in funs]
    return funs_out

【讨论】:

但是为什么其他选项不起作用? 你能详细说明你的答案吗?或者你能给我一些解释吗?我想了解您的解决方案/我的错误。 是的。请在此处查找更多信息:docs.python.org/3.9/faq/…

以上是关于更改函数列表时出现意外结果(lambda)[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用jq选择对象时出现意外结果

Fuelphp ORM添加到模型属性时出现意外结果

当C ++将元素从函数的返回值存储到std :: vector时出现意外的结果

在 Java 中创建列表列表时出现意外输出

声明全局 lambda C++ 时出现问题 [重复]

在 QueryBuilder 中使用动态输入时出现意外结果