【问题标题】:decorate a Python3 function to ignore *args in (a, b, *args, **kwargs)?装饰 Python3 函数以忽略 (a, b, *args, **kwargs) 中的 *args?
【发布时间】:2013-06-21 01:10:21
【问题描述】:

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]

【问题讨论】:

  • 我不理解你的例子。在list_args(1, 2, "non-positional arg") 中,"non-positional arg" 仍然是一个位置参数,尽管名称令人困惑。
  • 顺便说一下,“命名位置参数”(或有时是“固定位置参数”)是我自己对“位置或关键字和仅位置,但不是可变位置”的简写,因为实际上,这些东西并没有正式的术语……

标签: python python-3.x decorator


【解决方案1】:

我认为您误解了您使用的术语。

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 是一个可变位置参数ef关键字参数;而kw 是一个var-keyword 参数。 (没有仅位置参数的示例,因为它们不能出现在函数定义中;您必须编写 C/Java/.NET/RPython/whatever 扩展代码,或者创建 code 对象手动获取它们。)

在调用中,12位置参数3457关键字参数dceg关键字标识符

Python 会将两个位置参数匹配到前两个 positional-only 或 positional-or-keyword 参数,或者如果没有足够的 var-positional 参数,然后将关键字参数匹配到 positional-or -keyword 或具有相同名称的仅限关键字的参数,如果未找到名称,则为 var-keyword 参数。所以,里面foo

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

既然您已经了解了所有这些,那么让我坐下来有点困惑:有时 Python 使用 不同 术语,“形式参数”而不是“参数”和“实际参数”的“论据”。大多数情况下,您只能在源代码最古老的部分中找到这一点,但有时它会浮出水面。


那么,您要求什么可以忽略非位置参数。换句话说,您想接受但忽略关键字参数。这很简单:只需使用 var-keyword 参数接受它们,不要传递它们:

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

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

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

很难找到关于不同类型成员的确切参考,而且当你这样做时也很难理解……但幸运的是,inspect 文档将所有这些信息汇总在一个方便的图表中。

你可以看到一个函数没有任何看起来像它的参数签名的东西……但它包含一个代码对象,。当然,代码对象是在 Python 只有 2 种参数的时候设计的,它们被称为“形式参数”而不是“参数”,所以你在这里想要的是 co_argcount 可能不是很明显——但是相信我,是的。

所以:

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

根据您想对关键字参数执行的操作(请记住,它可能与命名的位置或关键字或仅位置参数匹配!),您可能还想对**kwco_varnames 执行某些操作.

【讨论】:

    猜你喜欢
    • 2018-08-28
    • 2013-09-25
    • 2016-04-20
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 2014-04-26
    • 2013-08-04
    相关资源
    最近更新 更多