简体   繁体   English

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

[英]decorate a Python3 function to ignore *args in (a, b, *args, **kwargs)?

Python 3.3: Can I decorate a function to ignore all positional arguments that do not match named parameters? 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]

I think you're misunderstanding the terms you're using. 我认为您误会了所使用的术语。

Arguments are the values passed to a function call . 参数是传递给函数调用的值。 Positional arguments are the ones without keywords. 位置参数是没有关键字的参数。

Parameters are the names in a function definition . 参数函数定义中的名称。 There are three different kinds of positional parameters; 有三种不同的位置参数; collectively, they're the ones up to and including the * parameter or bare * (if any). 总的来说,它们是包括*参数或裸* (如果有的话)的那些。

For example, in this code: 例如,在此代码中:

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)

a , b , c , and d are all positional-or-keyword parameters ; abcd都是位置或关键字参数 ; args is a var-positional parameter ; args是一个变量位置参数 ; e and f are keyword-only parameters ; ef仅限关键字的参数 ; and kw is a var-keyword parameter . kw是一个var-keyword参数 (No examples of positional-only parameters , because they can't appear in a function definition; you have to write C/Java/.NET/RPython/whatever extension code, or create code objects manually, to get them.) (没有仅位置参数的示例,因为它们不能出现在函数定义中;您必须编写C / Java / .NET / RPython /任何扩展代码,或手动创建code对象才能获得它们。)

In the call, 1 and 2 are positional arguments ; 在通话中, 12位置参数 3 , 4 , 5 , and 7 are keyword arguments ; 345 ,和7关键字参数 ; d , c , e , and g are keyword identifiers . dceg关键字标识符

Python will match the two positional arguments to the first two positional-only or positional-or-keyword parameters, or to the var-positional argument if there aren't enough, then match the keyword arguments up to the positional-or-keyword or keyword-only parameters with the same names, or to the var-keyword argument if the names aren't found. Python将两个位置参数与前两个仅位置或位置或关键字参数相匹配,或者如果没有足够的话,则与var-positional参数相匹配,然后将关键字参数与位置或关键字或key-only参数,具有相同的名称,如果找不到名称,则返回var-keyword参数。 So, inside foo : 因此,在foo内部:

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

Now that you have all of that straight, let me sit a bit of confusion back in: occasionally Python uses different terminology, "formal argument" instead of "parameter" and "actual argument" instead of "argument". 既然您已经掌握了所有这些内容,那么让我有些困惑:偶尔,Python使用不同的术语,“形式参数”代替“参数”,“实际参数”代替“参数”。 You mostly only find this deep in the oldest parts of the source code, but occasionally it bubbles up higher. 您大多只能在源代码的最古老部分找到这一点,但偶尔会出现更高的泡沫。


So, what you asked for what to ignore non-positional arguments. 那么,你要求什么忽略非位置参数。 In other words, you want to accept but ignore keyword arguments. 换句话说,您要接受但忽略关键字参数。 That's easy: just accept them with a var-keyword parameter, and don't pass them through: 这很简单:只需使用var-keyword参数接受它们,并且不要通过它们:

def wrapped(*args, **kwargs):
    return function_(*f_args)

However, what I think you wanted to ask for was how to ignore all arguments, positional or keyword, that don't match positional-only or positional-or-keyword parameters. 但是,我认为你要求的是如何忽略所有与位置或位置或关键字参数不匹配的参数,位置或关键字。

To do that, you'll need to inspect the signature of the wrapped function. 为此,您需要检查包装函数的签名。

The exact reference for what members different types have can be hard to find, and hard to understand when you do… but fortunately, the inspect documentation gathers it all together in a handy chart. 很难找到不同类型的成员的确切参考,并且当您这样做时也很难理解……但是幸运的是, inspect文档将所有这些信息汇总到了方便的图表中。

You can see that a function doesn't have anything that looks like its parameter signature… but it contains a code object, which does . 您会看到一个函数没有看起来像其参数签名的任何东西……但是它包含一个代码对象,它具有 Of course the code object was designed back when Python only had 2 kinds of parameters, and they were called "formal arguments" instead of "parameters", so it may not be immediately obvious that what you want here is co_argcount —but trust me, it is. 当然,当Python仅具有2种参数时,代码对象是经过重新设计的,它们被称为“形式参数”而不是“参数”,因此,您在这里想要的只是co_argcount可能不是很明显-但请相信我,它是。

So: 所以:

def wrapped(*args):
    return function_(*(args[:function_.__code__.co_argcount]))

Depending on what you want to do with keyword arguments (which, remember, may match named positional-or-keyword or positional-only parameters!), you may want to do something with **kw and co_varnames as well. 根据您想对关键字参数进行的操作(记住,这些参数可能与命名的position-or-keyword或仅positional的参数匹配!),您可能还想对**kwco_varnames进行操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM