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

Sha*_*hay 2 python decorator python-3.x

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]
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 7

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

参数是传递给函数调用的值.位置参数是没有关键字的参数.

参数函数定义中的名称.有三种不同的位置参数; 总的来说,它们是包含*参数或裸露的*(如果有的话).

例如,在此代码中:

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)
Run Code Online (Sandbox Code Playgroud)

a,b,c,和d都是位置-或关键字参数 ; args是一个变量位置参数 ; e并且f仅限关键字的参数 ; 并且kw是一个var-keyword参数.(没有仅位置参数的示例,因为它们不能出现在函数定义中;您必须编写C/Java/.NET/RPython /任何扩展代码,或code手动创建对象,以获取它们.)

在呼叫,1并且2位置参数 ; 3,4,5,和7关键字参数 ; d,c,e,和g关键字的标识符.

Python会将前两个位置参数或位置或关键字参数的两个位置参数匹配,如果没有足够的话,则匹配var-positional参数,然后将关键字参数与position-or-keyword或key-only参数,具有相同的名称,如果找不到名称,则返回var-keyword参数.所以,里面foo:

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

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


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

def wrapped(*args, **kwargs):
    return function_(*f_args)
Run Code Online (Sandbox Code Playgroud)

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

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

对于不同类型的成员所具有的确切参考可能很难找到,并且难以理解...但幸运的是,inspect文档将所有内容集中在一个方便的图表中.

你可以看到,一个函数不具有任何看起来像它的参数签名...但它包含一个代码对象,这确实.当然,当Python只有2种参数时,代码对象被设计回来了,它们被称为"形式参数"而不是"参数",所以你想要的东西可能不是很明显co_argcount- 但是相信我,它是.

所以:

def wrapped(*args):
    return function_(*(args[:function_.__code__.co_argcount]))
Run Code Online (Sandbox Code Playgroud)

根据你想用关键字参数做什么(这,记住,可以匹配命名位置,或关键字或位置,仅参数!),你可能需要做一些事情**kw,并co_varnames为好.