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

How to map function on all argument values, as a list? but have explicit argument names in the function definition

我想在函数定义中使用显式参数名称 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 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().

如果没有丑陋的黑客攻击,你想要做的事情是不可能的。您要么采用 *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,不适用于大多数其他解释器。它可能会在未来的某个版本中崩溃,因为它非常公然地依赖于解释器的实现细节。