装饰一个Python3函数来忽略(a,b,* args,** kwargs)中的* args?

时间:2013-06-21 01:10:21

标签: python python-3.x decorator

Python 3.3: 我可以修饰一个函数来忽略与命名参数不匹配的所有位置参数吗?

import functools
def ignore_star_args():
    def wrapper(function_):
        @functools.wraps(function_)
        def wrapped(*f_args):
            return function_(/*only named args*/)
        return wrapped
    return wrapper

@ignore_star_args()
def list_args(a, b, *args):
    # two positional arguments
    return [a, b] + list(args)

>>> list_args(1, 2, "non-positional arg")
[1, 2]

1 个答案:

答案 0 :(得分:7)

我认为你误解了你正在使用的术语。

Arguments是传递给function call的值。位置参数是没有关键字的参数。

Parametersfunction definition中的名称。有三种不同的位置参数;总的来说,它们是包括*参数或裸*(如果有)的那些。

例如,在此代码中:

def foo(a, b, c=3, d=4, *args, e, f=6, **kw): pass

foo(1, 2, d=3, c=4, e=5, g=7)

abcd都是位置或关键字参数; args var-positional参数; ef仅关键字参数; kw var-keyword参数。 (没有仅位置参数的示例,因为它们不能出现在函数定义中;您必须编写C / Java / .NET / RPython /任何扩展代码,或者创建{{1}手动对象来获取它们。)

在通话中,code1位置参数; 2345关键字参数; 7dce关键字标识符

Python将两个位置参数匹配前两个仅位置或位置或关键字参数,如果不足则匹配var-positional参数,然后匹配关键字参数直到位置 - 或-keyword或仅限关键字的参数,具有相同的名称,如果找不到名称,则返回var-keyword参数。所以,在g内:

foo

既然你已经完成了所有这些,那么让我有点困惑:偶尔Python使用不同的术语,“形式参数”而不是“参数”和“实际参数”代替“论证”。您大多只能在源代码的最古老部分找到这一点,但偶尔会冒出更高的气泡。


那么,你要求忽略非位置参数的内容。换句话说,您希望接受但忽略关键字参数。这很简单:只需使用var-keyword参数接受它们,并且不要通过它们:

a, b, c, d, args, e, f, kw = 1, 2, 4, 3, (), 5, 6, {'g': 7}

但是,我认为你想要要求的是如何忽略所有与位置或位置或关键字参数不匹配的参数,位置或关键字。

为此,您需要检查包装函数的签名。

成员不同类型的确切参考可能很难找到,而且很难理解......但幸运的是,inspect文档将它们全部收集在一个方便的图表中。

你可以看到一个函数没有看起来像它的参数签名的东西......但它包含一个代码对象, 。当然,当Python只有2种参数时,代码对象被设计回来了,它们被称为“形式参数”而不是“参数”,所以你想要的东西def wrapped(*args, **kwargs): return function_(*f_args) 可能不是很明显 - 但相信我,是的。

所以:

co_argcount

取决于你想要用关键字参数做什么(记住,可以匹配命名的位置或关键字或仅位置参数!),你可能希望对def wrapped(*args): return function_(*(args[:function_.__code__.co_argcount])) 和{{1同样。