Dưới đây là một giải pháp khá tổng quát rằng sẽ đối xử với docstring ban đầu của bạn làm mẫu, và duy trì thông tin khác về trang trí chức năng (như tên gọi của nó):
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)
trước f
là lần đầu tiên được gọi là, help(f)
trong thông dịch viên tương tác mang đến cho bạn:
Help on function f in module __main__:
f(*args, **kwargs)
%(name)s was called with %(signature)s and returned %(ret_val)r.
Sau khi nó được gọi là, bạn nhận được:
f(*args, **kwargs)
f was called with 3, 'marty' and returned 8.
Hoặc với một hàm tổng quát hơn, khoe 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.
Rõ ràng, bạn có thể tạo ra bất cứ điều gì biến bạn muốn sử dụng trong mẫu bên wrapper
.