我对装饰器还不够好...还是可以定义一个装饰器 live_doc ,它允许我在方法或函数调用后得到插值的文档字符串,填充用实际的参数和返回值。
@live_doc("f was called with %d, %s and returned %d")
def f(x, y):
x + len(y)
在下面的代码之后:
f(3, "marty")
d = f.doc
d 应该是“f被叫3,”marty“,并返回8”。在访问f.doc之前,我宁愿不构建字符串,但肯定需要松开调用args&某处返回价值。
答案 0 :(得分:1)
这是一个有点概括的解决方案,可以处理原始文档字符串 作为模板,并维护有关装饰函数的其他信息 (就像它的名字一样):
from functools import wraps
def live_doc(func):
template = func.__doc__
@wraps(func)
def wrapper(*args, **kwargs):
ret_val = func(*args, **kwargs)
args_pretty = ", ".join(repr(a) for a in args)
kw_pretty = ", ".join("%s=%r" % (k, v) for k, v in kwargs.items())
signature = ", ".join(x for x in (args_pretty, kw_pretty) if x)
name = func.__name__
wrapper.__doc__ = template % locals()
return ret_val
return wrapper
@live_doc
def f(x, y):
"""%(name)s was called with %(signature)s and returned %(ret_val)r."""
return x + len(y)
首次调用f
之前,交互式解释器中的help(f)
会为您提供:
Help on function f in module __main__:
f(*args, **kwargs)
%(name)s was called with %(signature)s and returned %(ret_val)r.
调用之后,你得到:
f(*args, **kwargs)
f was called with 3, 'marty' and returned 8.
或者使用更一般的功能,炫耀kwargs
:
@live_doc
def q(*args, **kwargs):
"""%(name)s was called with %(signature)s and returned %(ret_val)r."""
return len(args) + len(kwargs)
>>> q(1, 2, 3, a=7, b="foo")
5
>>> help(q)
q(*args, **kwargs)
q was called with 1, 2, 3, a=7, b='foo' and returned 5.
显然,您可以在wrapper
内的模板中创建想要使用的任何变量。
答案 1 :(得分:0)
这是我的代码,(我觉得写它很傻,所以我可能做错了,特别是在t
的中间部分):
def live_doc(d):
def f_d(f):
def f_new(*args):
r = f(*args)
t = [a for a in args]
t.append(r)
t = tuple(t)
f_new.doc = d % t
return r
return f_new
return f_d
@live_doc("f was called with %d, %s and returned %d")
def f(x,y):
return x + len(y)
f(1,"hi")
print(f.doc)
// f was called with 1, hi and returned 3
我使用的是http://www.python.org/dev/peps/pep-0318/
@decomaker(argA, argB, ...)
def func(arg1, arg2, ...):
pass
相当于
func = decomaker(argA, argB, ...)(func)
答案 2 :(得分:0)
我想出了这个:
#!/usr/bin/env python
def docme(func):
def wrap(*args, **kwargs):
retval = None
wrap.__doc__ = wrap.__olddoc__ + """
Last called with args: %s, %s
""" % (args, kwargs)
try:
retval = func(*args, **kwargs)
wrap.__doc__ += 'Last returned: %s' % retval
return retval
except Exception as exc:
wrap.__doc__ += 'Failed and raised: %r' % exc
raise
wrap.__doc__ = func.__doc__ + '\n\nHas not been called yet'
wrap.__name__ = func.__name__
wrap.__olddoc__ = func.__doc__
return wrap
@docme
def foo(x):
"""foo docs"""
if x == 1:
raise ValueError('baz')
return x * 2
它维护函数的doc字符串,因此您仍然可以调用help(foo)
来阅读其指令。在每次调用时,它都会使用参数和结果(或引发的异常)更新docstring:
>>> print foo.__doc__
foo docs
Has not been called yet
>>> foo(2)
4
>>> print foo.__doc__
foo docs
Last called with args: (2,), {}
Last returned: 4
>>> foo(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/tmp/foo.py", line 11, in wrap
retval = func(*args, **kwargs)
File "/tmp/foo.py", line 27, in foo
raise ValueError('baz')
ValueError: baz
>>> print foo.__doc__
foo docs
Last called with args: (1,), {}
Failed and raised: ValueError('baz',)