【问题标题】:Decorator that adds a keyword parameter添加关键字参数的装饰器
【发布时间】:2017-07-26 09:42:24
【问题描述】:

我正在尝试定义一个装饰器,它只向装饰函数f 添加一个关键字参数。 f 可能有(位置、关键字等)参数的任意组合。我试过这个:

def capture_wrap(f):
    def captured(name=False, *args, **kwargs):
        """name can be False, True or str. if str, then use it as a name."""
        print (name, f, args, kwargs)
        inner = f(*args, **kwargs)
        if name is False:
            return inner
        elif name is True:
            return capture(inner)
        else:
            return capture(inner, name=name)
    return captured

如果我尝试将它与接受单个参数的函数一起使用:

@capture_wrap
def any_of(s):
    """s must be in the right format.
    See https://docs.python.org/3/library/re.html#regular-expression-syntax ."""
    return wrap('[', Dinant(s, escape=False), ']')
0-9A-Fa-f <function any_of at 0x7fb370548a60> () {}
Traceback (most recent call last):
File "./dinant.py", line 222, in <module>
    hex = one_or_more(any_of('0-9A-Fa-f'))
File "./dinant.py", line 116, in captured
    inner = f(*args, **kwargs)
TypeError: any_of() missing 1 required positional argument: 's'

我收到一个错误,因为 any 参数变成了 captured() 中的 name 参数。我应该怎么做才正确?

【问题讨论】:

  • 您能否解释一下“capture()”是什么以及您真正想要实现的目标(=> 您试图用这个解决的问题 - 目前无法解决 - 解决方案)?
  • 你能清楚你在 s 中传递了什么以及为什么需要它吗?这将有助于给出更明确的答案

标签: python python-3.x function decorator


【解决方案1】:

您可以将name 设为keyword-only argument 来实现此目的。目前的问题是它是一个位置参数,当你在做 any_of('foo') 时,'foo' 被传递给 name 参数。

def capture_wrap(f):
    def captured(*args, name=False, **kwargs):
        """name can be False, True or str. if str, then use it as a name."""
        print(name, f, args, kwargs)
        inner = f(*args, **kwargs)
        return inner
    return captured


@capture_wrap
def any_of(s1, s2, s3, **kwargs):
    return "I do something"

演示:

>>> any_of('0-9A-Fa-f', 1, 2)
False <function any_of at 0x1041daea0> ('0-9A-Fa-f', 1, 2) {}
'I do something'

>>> any_of('0-9A-Fa-f', 2, 3, a=1, b=2, name='some-name')
some-name <function any_of at 0x1041daea0> ('0-9A-Fa-f', 2, 3) {'a': 1, 'b': 2}
'I do something'

【讨论】:

  • @MosesKoledoye 他们在代码中使用 print() 作为函数,其输出不是元组。此外,错误消息 TypeError: any_of() missing 1 required positional argument: 's' 是特定于 Python 3 的。
  • 这就是我最终的做法。我只是忘记/不知道这是有效的语法。
  • @MarcosDione 仅在 Python 3 中引入。
  • 好吧,在这一点上,在它发布将近 9 年后,我们应该将 py3 称为纯 Python,并将 py2 称为“Python legacy”:)
【解决方案2】:

只需在调用函数 f 的位置传递名称 内部 = f(name, *args, **kwargs)

【讨论】:

    猜你喜欢
    • 2018-02-23
    • 2010-12-23
    • 2019-06-14
    • 1970-01-01
    • 2021-05-08
    • 2023-02-10
    • 2012-02-20
    • 2019-02-10
    • 2020-02-06
    相关资源
    最近更新 更多