2012-11-29 10 views
5

Tôi không đủ tốt với trang trí chưa làm điều này ... Có thể xác định một trang trí live_doc cho phép tôi có được một chuỗi doc nội suy sau một phương thức hoặc một hàm gọi, được điền vào với các đối số thực tế và giá trị trả về.Làm thế nào để xác định một trang trí sẽ cung cấp một chuỗi doc nội suy cho một hàm/phương thức gọi

@live_doc("f was called with %d, %s and returned %d") 
def f(x, y): 
    x + len(y) 

Sau khi vào mã bên dưới:

f(3, "marty") 

d = f.doc 

d nên "f được gọi với 3, "Marty", và trở về 8". Tôi không muốn xây dựng các chuỗi cho đến khi f.doc được truy cập, nhưng chắc chắn sẽ cần phải gửi đi cuộc gọi args & giá trị trả về ở đâu đó.

Trả lời

1

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 .

0

Đây là mã của tôi, (và tôi cảm thấy khá ngớ ngẩn viết nó, vì vậy tôi có thể làm điều gì đó sai, đặc biệt là ở phần giữa với 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 

tôi sử dụng từ http://www.python.org/dev/peps/pep-0318/ rằng

@decomaker(argA, argB, ...) 
def func(arg1, arg2, ...): 
    pass 

tương đương với

func = decomaker(argA, argB, ...)(func) 
0

tôi đến với điều này:

#!/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 

Nó duy trì chuỗi tài liệu của hàm để bạn vẫn có thể gọi help(foo) để đọc hướng dẫn của hàm. Trên mỗi cuộc gọi, nó cập nhật mà docstring với lập luận và kết quả (hoặc ngoại trừ nó lớn lên):

>>> 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',) 
Các vấn đề liên quan