如何将所有参数值的函数映射为列表?但在函数定义中有明确的参数名称

Posted

技术标签:

【中文标题】如何将所有参数值的函数映射为列表?但在函数定义中有明确的参数名称【英文标题】:How to map function on all argument values, as a list? but have explicit argument names in the function definition 【发布时间】:2018-10-23 15:47:07 【问题描述】:

我想在函数定义中使用显式参数名称ff(a,b,c) 来定义一个函数,但我还想将一个函数映射到所有参数上以获得一个列表:

ff(a,b,c):
    return list(map(myfunc,[a,b,c]))

但是,我不想在函数内显式地将参数名称写为 a、b、c。我想这样做

ff(a,b,c):
    return list(map(myfunc,getArgValueList()))

getArgValueList() 将按顺序检索参数值并形成一个列表。这个怎么做?有没有像getArgValueList()这样的内置函数?

【问题讨论】:

使用*args作为参数。 @Code-Apprentice OP说“我希望参数接口是明确的。即在进行函数定义时明确将参数名称写为ff(a,b,c)”,甚至编辑了问题以将其放入在你对答案做出你的 cmets 之后加粗,所以......我认为,即使这可能是 OP 应该想要的,它也不是 OP确实想要的。 @smci 我不认为它是重复的。 OP想要做的是定义一个带有显式参数的函数,但无论如何都要获取args列表。这是一件不寻常的事情,因此它不会与涉及可变参数或 splats 的明显重复操作相匹配,即使乍看之下也是如此。 @PM2Ring 这比 Python 更不习惯 Java。它是……也许是(ES5 之前的)javascript,但实际上它比其他任何东西都更像 Perl。 @abarnert 好的。我只是猜测它是 Java 的东西,主要来自 camelCase 函数名(我不写 Java)。 【参考方案1】:

如果没有丑陋的 hack,您要尝试做的事情是不可能的。您可以使用*args 并获取一系列参数值,您可以将其用作args

def ff(*args):
    return list(map(myfunc, args))

… 或者您采用三个显式参数并按名称使用它们:

def ff(a, b, c):
    return list(map(myfunc, (a, b, c)))

……但它是其中之一,而不是两者。

当然,如果您愿意,您可以自己将这些值按顺序排列:

def ff(a, b, c):
    args = a, b, c
    return list(map(myfunc, args))

……但我不确定这会给你带来什么。


如果你真的想知道如何编写getArgValueList 函数,我会解释如何去做。但是,如果您希望使您的代码更易读、更高效、更惯用、更易于理解、更简洁或几乎其他任何东西,那么它将产生完全相反的效果。我能想象做这样的事情的唯一原因是如果你必须动态生成函数或其他东西——即使那样,我也想不出你不能只使用*args 的原因。但是,如果你坚持:

def getArgValueList():
    frame = inspect.currentframe().f_back
    code = frame.f_code
    vars = code.co_varnames[:code.co_argcount]
    return [frame.f_locals[var] for var in vars]

如果你想知道它是如何工作的,大部分都在 inspect 模块文档中:

currentframe() 获取当前帧——getArgValueList 的帧。 f_back 获取父框架 - 调用 getArgValueList 的人的框架。 f_code 获取从调用getArgValueList 的函数体编译的代码对象。 co_varnames 是该正文中所有局部变量的列表,以参数开头。 co_argcount 是显式位置或关键字参数的计数。 f_locals 是一个带有框架的 locals() 环境副本的字典。

这当然只适用于不接受 *args、仅关键字参数或 **kwargs 的函数,但您可以通过一些工作将其扩展为也适用于它们。 (详见co_kwonlyargcountco_flagsCO_VARARGSCO_VARKEYWORDS。)

此外,这仅适用于 CPython,不适用于大多数其他解释器。它可能会在未来的某个版本中中断,因为它非常明显地依赖于解释器的实现细节。

【讨论】:

嗨,@abarnert。非常感谢您花这么多时间回答。我学到了很多。但似乎getArgValueList 工作不正常。如果我将def getArgValueList(a,b,c): 定义为def getArgValueList(a,b,c):,则getArgValueList(1,2,3) 给出() @user15964 为什么你把它定义为getArgValueList(a,b,c)。您想要一个可以从任何函数调用为getArgValueList() 的函数。那是我给你的。和it works。如果在不理解的情况下随意将其更改为不同的东西是行不通的,那就不足为奇了。 哦,对不起。我的大脑之前一定是乱了套。它确实有效。非常感谢,我决定接受你的回答,因为你提供了明确的getArgValueList。虽然 jferard 的方案也行得通,但通过他的方法构造getArgValueList 似乎并不容易。 @user15964 是的,Python 使 可能 做各种聪明的事情,但是那些通常太聪明而不是好主意的事情,它通常会有点不愉快。【参考方案2】:

*args construction 会将参数作为列表提供给您:

>>> def f(*args): return list(map(lambda x:x+1, args))
>>> f(1,2,3)
[2, 3, 4]

如果您绑定了f 的签名,则必须使用inspect 模块:

import inspect

def f(a, b,c):
    f_locals = locals()
    values = [f_locals[name] for name in inspect.signature(f).parameters]
    return list(map(lambda x:x+1, values))

inspect.signature(f).parameters 以正确的顺序为您提供参数列表。值在locals()

【讨论】:

不应该是print(f(1, 2, 3))吗? @Code-Apprentice @jferard 非常感谢。但实际上我希望参数接口是明确的。所以我必须写ff(a,b,c) @Code-Apprentice 如果应该是f(1,2,3),那么函数也应该是list(map(lambda x:x+1, args)) 正如所写,此函数不接受 3 个参数,它接受一个参数,即 3 个元素的列表。如果您想这样做,则根本不需要 splat — 只需 def f(lst): return list(map(lambda x: x+1, lst)) @user15964 调用函数或者定义函数的时候一定要写ff(a,b,c)

以上是关于如何将所有参数值的函数映射为列表?但在函数定义中有明确的参数名称的主要内容,如果未能解决你的问题,请参考以下文章

如何定义一个使用 Python 读取并返回列表中所有值的函数?

python中是如何实现将一个函数中定义的变量在另一个函数中改变其值的

如何在Python中定义静态变量

R用户定义函数,返回多个类型对象

请问这个C语言中有参数的函数是怎么传递值的,调用的时候没有参数啊。

C++ —— 函数默认参数