【发布时间】:2016-04-22 07:35:30
【问题描述】:
我是 python 和装饰器的新手,在编写一个装饰器时遇到了困难,它不仅报告传递的 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 调用中传递的 args,但没有报告 square 定义中定义的默认 kwargs。报告 kwargs 的唯一方法是如果它们从默认值更改,即传递给 square 调用。
关于如何获得方形定义中的 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
那是一次很好的学习经历。很高兴看到同一问题的三种不同解决方案。感谢回答者!
【问题讨论】:
-
@Martijn,谢谢;我已经阅读了您答案的前两行,并且会离开,了解有关检查的所有信息,然后看看我想出了什么。然后会回来看看如何真正做到这一点;-)
标签: python decorator default python-decorators keyword-argument