2012-11-29 41 views
5

के लिए एक इंटरपोलेटेड दस्तावेज़ स्ट्रिंग प्रदान करेगा, मैं अभी तक ऐसा करने के लिए सजावट करने वालों के साथ पर्याप्त नहीं हूं ... क्या एक सजावट को परिभाषित करना संभव है 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 

होना चाहिए मार्टी "च 3 के साथ बुलाया गया था," ", और 8 लौटे"। मैं f.doc तक पहुंचने तक स्ट्रिंग्स का निर्माण नहीं करना चाहूंगा, लेकिन निश्चित रूप से कहीं भी & वापसी मूल्य पर कॉल को गिलहरी करने की आवश्यकता होगी।

उत्तर

1

यहाँ कुछ हद तक एक सामान्यीकृत समाधान सजाया बारे में अन्य जानकारी टेम्पलेट के रूप में अपने मूल 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) 

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 अंदर टेम्पलेट में उपयोग करना चाहता था ।

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) 
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 

यह समारोह के डॉक स्ट्रिंग को बनाए रखता है ताकि आप अभी भी 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',)