我是python和decorators的新手,在编写一个decorator时遇到了麻烦,它不仅报告传递的args和kwargs,而且报告未更改的默认kwargs
这就是我目前所拥有的
def document_call(fn):
def wrapper(*args, **kwargs):
print 'function %s called with positional args %s and keyword args %s' % (fn.__name__, args, kwargs)
return fn(*args, **kwargs)
return wrapper
@document_call
def square(n, trial=True, output=False):
# kwargs are a bit of nonsense to test function
if not output:
print 'no output'
if trial:
print n*n
square(6) # with this call syntax, the default kwargs are not reported
# function square called with positional args (6,) and keyword args {}
# no output
36
square(7,output=True) # only if a kwarg is changed from default is it reported
# function square called with positional args (7,) and keyword args {'output': True}
49
“问题”在于,此装饰器报告在对square的调用中传递的参数,但不报告square定义中定义的默认kwargs。报告KWARG的唯一方法是将KWARG从默认值更改为方形调用
关于如何在方形定义中报告kwargs,有什么建议吗
在跟进检查建议后进行编辑,这有助于我找到下面的解决方案。我更改了位置参数的输出,以包括它们的名称,因为我认为这使输出更容易理解
import inspect
def document_call(fn):
def wrapper(*args, **kwargs):
argspec = inspect.getargspec(fn)
n_postnl_args = len(argspec.args) - len(argspec.defaults)
# get kwargs passed positionally
passed = {k:v for k,v in zip(argspec.args[n_postnl_args:], args[n_postnl_args:])}
# update with kwargs
passed.update({k:v for k,v in kwargs.iteritems()})
print 'function %s called with \n positional args %s\n passed kwargs %s\n default kwargs %s' % (
fn.__name__, {k:v for k,v in zip(argspec.args, args[:n_postnl_args])},
passed,
{k:v for k,v in zip(argspec.args[n_postnl_args:], argspec.defaults) if k not in passed})
return fn(*args, **kwargs)
return wrapper
那是一次很好的学习经历。看到同一个问题有三种不同的解决方案是很好的。感谢回答者
由于decorator函数
wrapper
接受任何参数并只传递所有内容,因此它当然不知道包装函数的参数及其默认值因此,如果不实际查看修饰函数,您将无法获得此信息。幸运的是,您可以使用inspect模块找出包装函数的默认参数
您可以使用
inspect.getargspec
函数来获取有关函数签名中默认参数值的信息。您只需将它们与参数名称正确匹配:请注意,您仍然可以对此进行改进,因为现在您正在分别处理位置参数和命名参数。例如,在
square
函数中,还可以通过将trial
作为位置参数传递到n
之后来设置它。这将使它不会出现在kwargs
中。因此,您必须将位置参数与kwargs匹配才能获得完整信息。您可以从argspec
获取有关位置的所有信息您必须反思您包装的函数,才能读取默认值。您可以使用^{} function 实现这一点
该函数返回一个元组,其中包括所有参数名称的序列和默认值的序列。最后一个参数名称与默认值配对,形成名称默认值对;您可以使用它创建字典并从中提取未使用的默认值:
您需要考虑到位置参数也可以指定默认参数,因此找出关键字参数的过程要复杂一些,但如下所示:
这将从传入的位置参数和关键字参数中确定实际使用的关键字参数,然后提取未使用的默认值
演示:
从Python 3.5开始,您可以使用^{} 用默认值填充缺少的参数:
相关问题 更多 >
编程相关推荐