元のdocstringをテンプレートとして扱い、装飾された関数に関する他の情報(名前など)を維持する、やや一般化されたソリューションを次に示します。
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)
Beforef
が最初に呼び出されると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
。