【发布时间】:2020-03-11 10:34:05
【问题描述】:
我有多个类,其中许多对一个参数具有相同的初始化代码。因此我想用包装器添加参数。
由于代码已经在生产中并且此参数在所有调用中都是最后一个,但签名具有不同的长度并且参数只能是位置,因此从 args 和 @ 中“捕获”此参数并非易事987654322@.
下面的“有效”,只要step 是kwarg,但如果不是,它在*args 中并将被传递给函数,因为它有太多参数而正确抛出:
def stepable(func):
@functools.wraps(func)
def wrapper(self, *args, step=1, **kwargs):
func(self, *args, **kwargs)
self.step = step # and other stuff, depending on step
return wrapper
但即使我会用len(args)>len(inspect.signature(func).parameters) 捕获它(函数参数中没有*args)显示给用户的签名是错误的(因为我使用了@wraps)。
如何添加参数(/default) 以便inspect 得到它?或者基本上是“做functools.partial的逆操作”?
【问题讨论】:
-
既然你说是最后一个参数,那
func(self, *args[:-1], **kwargs); self.step = args[-1]呢? -
感谢您的建议@a_guest!是的,这就是我想说的“但即使我 [w]...”。但是我如何向用户展示这个函数接受
step作为参数呢? -
您可以将其添加到
__doc__字符串中。如果您使用wraps,签名将保持不变。这就是它的工作原理。从您的描述来看,无论如何使用装饰器是不寻常的。创建一个子类并在那里执行初始化似乎更干净。 -
如果原始方法之一具有 VAR_POSITIONAL (
*args) 参数,例如def func(a, b=1, *args),应该怎么做?您希望包装后的函数签名为def func(a, b=1, step=1, *args)还是def func(a, b=1, *args),step是*args的最后一个元素,没有默认值? -
@SergeBallesta 这是一个有效的评论,也是我写“函数[参数]中没有
*args”的原因。我的情况不需要它,但def func(a, b=1, step=1, *args)可能是合适的东西