gpt4 book ai didi

python - 带参数的装饰器

转载 作者:行者123 更新时间:2023-11-28 21:40:37 26 4
gpt4 key购买 nike

我有一组具有(大部分)共享参数但不同进程的函数。我想使用装饰器将每个参数的描述添加到函数的标题级文档字符串中。

我试图模仿 this answer 中的结构通过在 appender 中合并嵌套函数但失败了。我也试过 functools.partial 但有些地方有点不对劲。

我的尝试:

def appender(func, *args):
"""Appends additional parameter descriptions to func's __doc__."""
def _doc(func):
params = ''.join([defaultdocs[arg] for arg in args])
func.__doc__ += '\n' + params
return func
return _doc

defaultdocs = {

'a' :
"""
a : int, default 0
the first parameter
""",

'b' :
"""
b : int, default 1
the second parameter
"""
}

@appender('a')
def f(a):
"""Title-level docstring."""
return a

@appender('a', 'b')
def g(a, b):
"""Title-level docstring."""
return a + b

这失败了,我相信它失败了,因为传递给 appender 的第一个 arg 被解释为 func。因此,当我查看 g 的结果文档字符串时,我得到:

print(g.__doc__)
Title-level docstring.

b : int, default 1
the second parameter

因为,当我希望它成为 *args 的第一个元素时,'a' 被解释为 'func' .我该如何纠正这个问题?

期望的结果:

print(g.__doc__)
Title-level docstring.

a : int, default 0
the first parameter

b : int, default 1
the second parameter

最佳答案

发生这种情况是因为您传递的变量名称实际上被捕获到 func 参数中。

为了在 Python 中实现可调用装饰器,您需要对函数进行两次编码,使用外部函数来接受装饰器参数,使用内部函数来接受原始函数。可调用装饰器只是返回其他装饰器的高阶函数。例如:

def appender(*args):  # This is called when a decorator is called,
# e. g. @appender('a', 'b')
"""Appends additional parameter descriptions to func's __doc__."""
def _doc(func): # This is called when the function is about
# to be decorated
params = ''.join([defaultdocs[arg] for arg in args])
func.__doc__ += '\n' + params
return func
return _doc

外部 (appender) 函数充当新装饰器的工厂,而 _doc 函数是一个实际的装饰器。总是这样传递:

  • 将装饰器参数传递给外部函数
  • 将原始函数传递给内部函数

一旦 Python 看到这个:

@appender('a', 'b')
def foo(): pass

...它会在引擎盖下做这样的事情:

foo = appender('a', 'b')(foo)

...扩展为:

decorator = appender('a', 'b')
foo = decorator(foo)

由于 Python 中作用域的工作方式,每个新返回的 _doc 函数实例都将具有来自外部函数的自己的本地 args 值。

关于python - 带参数的装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45425830/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com