2012-01-11 16 views
39

मैं फ़ंक्शन के अंदर से एक पायथन फ़ंक्शन के डॉकस्ट्रिंग को मुद्रित करना चाहता हूं। उदाहरण के लिए ।फ़ंक्शन के अंदर से पाइथन फ़ंक्शन के डॉकस्ट्रिंग को प्रिंट कैसे करें?

def my_function(self): 
    """Doc string for my function.""" 
    # print the Docstring here. 

फिलहाल मैं my_function के बाद सीधे यह कर रहा हूं परिभाषित किया गया है।

print my_function.__doc__ 

लेकिन यह कार्य स्वयं ही ऐसा करने देगा।

मैंने अपने_फंक्शन के अंदर print self.__doc__print self.my_function.__doc__ और print this.__doc__ पर कॉल करने का प्रयास किया है लेकिन यह काम नहीं किया।

उत्तर

48
def my_func(): 
    """Docstring goes here.""" 
    print my_func.__doc__ 

यह जब तक आप ऑब्जेक्ट नाम my_func करने के लिए बाध्य नहीं बदलते हैं, के रूप में काम करेंगे।

new_func_name = my_func 
my_func = None 

new_func_name() 
# doesn't print anything because my_func is None and None has no docstring 

जिन स्थितियों में आप ऐसा करेंगे, वे दुर्लभ हैं, लेकिन वे होते हैं।

हालांकि, अगर आप इस तरह की एक डेकोरेटर लिखें:

def passmein(func): 
    def wrapper(*args, **kwargs): 
     return func(func, *args, **kwargs) 
    return wrapper 

अब आप यह कर सकते हैं:

@passmein 
def my_func(me): 
    print me.__doc__ 

और यह अपने कार्य (जो खुद के लिए एक संदर्भ self के समान हो जाता है कि यह सुनिश्चित करेंगे) के पहले तर्क के रूप में, तो यह हमेशा सही कार्य के docstring प्राप्त कर सकते हैं। यदि किसी विधि पर उपयोग किया जाता है, तो सामान्य self दूसरा तर्क बन जाता है।

+7

मुझे वास्तव में आपकी सजावट विधि पसंद है। फ्रेम निरीक्षण से अधिक पाइथोनिक और कम जोखिम भरा, और आपको फ़ंक्शन नाम का उपयोग करने से बचने की अनुमति देता है। Slick! Upvoted! – FlipMcF

+1

धन्यवाद, इसकी सराहना करें। :-) – kindall

+0

अंतिम कोड स्निपेट में my_func की तर्क सूची में * args और ** kwargs नहीं होना चाहिए? या अतिरिक्त तर्क केवल छोड़े गए थे, हालांकि प्रोग्रामर फ़ंक्शन परिभाषा में वांछित अतिरिक्त तर्क डाल सकता था। मुझे यकीन नहीं है कि यह स्पष्ट है, हालांकि यह पाठ में "इसके पहले तर्क के रूप में" कहता है। – RufusVS

1

प्रयास करें:

class MyClass(): 
    # ... 
    def my_function(self): 
     """Docstring for my function""" 
     print MyClass.my_function.__doc__ 
     # ... 

(*) था एक कॉलन (:) लापता my_function()

+0

खेद लोग मेरे मूर्खता self.my_function .__ doc__ वास्तव में काम करता है – shane87

4

के बाद यह काम करता है:

def my_function(): 
    """Docstring for my function""" 
    #print the Docstring here. 
    print my_function.__doc__ 

my_function() 

अजगर 2.7.1

इस में यह भी काम करता है:

class MyClass(object): 
    def my_function(self): 
     """Docstring for my function""" 
     #print the Docstring here, either way works. 
     print MyClass.my_function.__doc__ 
     print self.my_function.__doc__ 


foo = MyClass() 

foo.my_function() 

हालांकि यह अपने आप ही काम नहीं करेगा:

class MyClass(object): 
    def my_function(self): 
     """Docstring for my function""" 
     #print the Docstring here. 
     print my_function.__doc__ 


foo = MyClass() 

foo.my_function() 

NameError: वैश्विक नाम 'my_function' परिभाषित नहीं है

+0

आपकी कक्षा विधि केवल वैश्विक नामस्थान में, पहले एक फ़ंक्शन के रूप में my_function को परिभाषित करने के कारण काम करती है। इसे ताजा पायथन उदाहरण के साथ आज़माएं;) –

+0

@jgritty आपने अपने दूसरे स्निपेट का परीक्षण नहीं किया। यह – eyquem

+0

@Alex लीच काम नहीं करता है क्या आपने कक्षा के साथ स्निपेट का परीक्षण किया था? यह वास्तव में काम नहीं करता है .... – eyquem

2

आप एक के बजाय एक वर्ग विधि की तरह अपने सवाल उठाया गया है समारोह। नामस्थान यहां महत्वपूर्ण हैं। फ़ंक्शन के लिए, print my_function.__doc__ ठीक है, क्योंकि my_function वैश्विक नेमस्पेस में है।

कक्षा विधि के लिए, print self.my_method.__doc__ जाने का रास्ता होगा।

यदि आप विधि का नाम निर्दिष्ट नहीं करना चाहते हैं, बल्कि इसके लिए एक चर को पास करना चाहते हैं, तो आप अंतर्निहित फ़ंक्शंस हैट्र (ऑब्जेक्ट, विशेषता) और गेटैटर (ओबीजे, एटीआर) का उपयोग कर सकते हैं, जो करते हैं जैसा कि वे कहते हैं, आपको तारों के साथ एक विधि का नाम होने के साथ चर को पारित करने की इजाजत देता है। जैसे

class MyClass: 
    def fn(self): 
     """A docstring""" 
     print self.fn.__doc__ 

def print_docstrings(object): 
    for method in dir(object): 
     if method[:2] == '__': # A protected function 
      continue 
     meth = getattr(object, method) 
     if hasattr(meth , '__doc__'): 
      print getattr(meth , '__doc__') 

x = MyClass() 
print_docstrings(x) 
+0

क्या विधि नाम को दोहराने के लिए कोई अच्छा तरीका नहीं है? ऐसा कुछ .__ doc__ या कुछ? माफ करना नया पायथन .. – shane87

+0

वास्तव में नहीं, नहीं। –

+0

हाँ, वास्तव में नहीं .. मैंने dir (self.my_function) के माध्यम से एक नज़र डाली थी, और 'self.my_function .__ func__' शायद रुचि के रूप में देखा गया था, लेकिन फिर भी उस ऑब्जेक्ट मॉडल के माध्यम से इसे एक्सेस करने की आवश्यकता है। आप इस तरह के एक समारोह को जोड़ सकते हैं: 'विधि में डीआईआर (माइक्लास) के लिए विधि: यदि हैटट्र (getattr (MyClass, विधि), '__ doc__'): प्रिंट getattr (getattr (MyClass, विधि), '__doc__') ' –

7

यह काम करना चाहिए (मेरे परीक्षणों में यह भी आउटपुट शामिल है)। आप शायद getdoc के बजाय __doc__ का उपयोग कर सकते हैं, लेकिन मुझे यह पसंद है, इसलिए मैंने जो भी उपयोग किया है। साथ ही, आपको कक्षा/विधि/फ़ंक्शन के नाम जानने की आवश्यकता नहीं है।

कक्षा, एक विधि और एक समारोह दोनों के लिए उदाहरण। मुझे बताओ कि अगर यह नहीं है कि तुम क्या, वैश्विक में एक गतिशील देखने() निर्देशिका :)

from inspect import * 

class MySelfExplaningClass: 
    """This is my class document string""" 

    def __init__(self): 
     print getdoc(self) 

    def my_selfexplaining_method(self): 
     """This is my method document string""" 
     print getdoc(getattr(self, getframeinfo(currentframe()).function)) 


explain = MySelfExplaningClass() 

# Output: This is my class document string 

explain.my_selfexplaining_method() 

# Output: This is my method document string 

def my_selfexplaining_function(): 
    """This is my function document string""" 
    print getdoc(globals()[getframeinfo(currentframe()).function]) 

my_selfexplaining_function() 

# Output: This is my function document string 
+0

यह सबसे अच्छा जवाब है जिसे मैं वोट दूंगा। –

0

के रूप में उल्लेख किया कई बार देख रहे थे समारोह नाम का उपयोग कर रहा है। यह केवल परिभाषा के मॉड्यूल में और केवल वैश्विक कार्य के लिए काम करता है।

def foo(): 
    """ this is foo """ 
    doc = foo.__doc__ 
class Foo: 
    def bar(self): 
     """ this is bar """ 
     doc = Foo.bar.__doc__ 

के बराबर है: के रूप में इन नामों को काफी लंबे समय से प्राप्त कर सकते हैं जो काफी बोझिल है - आप एक सदस्य समारोह के डॉक स्ट्रिंग पता लगाना चाहते हैं, तो आप भी वर्ग के नाम से पथ देखने के लिए की आवश्यकता होगी
def foo(): 
    """ this is foo """ 
    doc = globals()["foo"].__doc__ 
class Foo: 
    def bar(self): 
     """ this is bar """ 
     doc = globals()["Foo"].bar.__doc__ 

आप कॉलर के डॉक स्ट्रिंग को देखने के लिए चाहते हैं, कि वैसे भी काम नहीं करेगा के रूप में अपने प्रिंट-हेल्पर एक पूरी तरह से अलग वैश्विक() शब्दकोश के साथ एक पूरी तरह से अलग मॉड्यूल में रहते हैं हो सकता है। स्टैक फ्रेम को देखने का एकमात्र सही विकल्प है - लेकिन पायथन आपको फ़ंक्शन ऑब्जेक्ट निष्पादित नहीं करता है, यह केवल "f_code" कोड ऑब्जेक्ट का संदर्भ है। लेकिन चलते रहें, क्योंकि उस समारोह के "f_globals" का भी संदर्भ है। तो आप कॉलर के दस्तावेज़ को इस तरह प्राप्त करने के लिए एक फ़ंक्शन लिख सकते हैं, और इससे भिन्नता के रूप में, आपको अपनी खुद की दस्तावेज़ स्ट्रिंग मिलती है।

import inspect 

def get_caller_doc(): 
    frame = inspect.currentframe().f_back.f_back 
    for objref in frame.f_globals.values(): 
     if inspect.isfunction(objref): 
      if objref.func_code == frame.f_code: 
       return objref.__doc__ 
     elif inspect.isclass(objref): 
      for name, member in inspect.getmembers(objref): 
       if inspect.ismethod(member): 
        if member.im_func.func_code == frame.f_code: 
         return member.__doc__ 

और यह परीक्षण करने के लिए चलते हैं: इस उत्पादन

this is foo 
this is bar 
None 
None 
showing my doc 

वास्तव में, ज्यादातर लोगों को अपने स्वयं के दस्तावेज़ स्ट्रिंग केवल यह हाथ नीचे एक तर्क के रूप चाहते हैं, उसमें

def print_doc(): 
    print get_caller_doc() 

def foo(): 
    """ this is foo """ 
    print_doc() 

class Foo: 
    def bar(self): 
     """ this is bar """ 
     print_doc() 

def nothing(): 
    print_doc() 

class Nothing: 
    def nothing(self): 
     print_doc() 

foo() 
Foo().bar() 

nothing() 
Nothing().nothing() 

# and my doc 

def get_my_doc(): 
    return get_caller_doc() 

def print_my_doc(): 
    """ showing my doc """ 
    print get_my_doc() 

print_my_doc() 

परिणाम, लेकिन कहा जाने वाला सहायक कार्य इसे अपने आप देख सकता है। मैं इसे अपने अनजान कोड में उपयोग कर रहा हूं जहां कभी-कभी कुछ लॉग भरने या परीक्षण डेटा के रूप में दस्तावेज़ स्ट्रिंग का उपयोग करने के लिए यह आसान होता है। यही कारण है कि प्रस्तुत get_caller_doc() केवल टेस्ट क्लास के वैश्विक परीक्षण कार्यों और सदस्य कार्यों की तलाश करता है, लेकिन मुझे लगता है कि अधिकांश लोगों के लिए पर्याप्त है जो दस्तावेज़ स्ट्रिंग के बारे में जानना चाहते हैं।

class FooTest(TestCase): 
    def get_caller_doc(self): 
     # as seen above 
    def test_extra_stuff(self): 
     """ testing extra stuff """ 
     self.createProject("A") 
    def createProject(self, name): 
     description = self.get_caller_doc() 
     self.server.createProject(name, description) 

sys._getframe साथ एक उचित get_frame_doc (फ्रेम) को परिभाषित करने के लिए (1) पाठक के लिए छोड़ दिया जाता है()।

1

ऐसा करने के लिए काफी सरल विधि है कि कोई भी अभी तक उल्लेख किया है नहीं है:

import inspect 

def func(): 
    """Doc string""" 
    print inspect.getdoc(func) 

और यह तुम क्या चाहते है।

यहां कुछ भी नहीं चल रहा है। यह सब कुछ हो रहा है कि एक फ़ंक्शन में func.__doc__ कर एट्रिब्यूट रिज़ॉल्यूशन को __doc__ पर देखने के लिए काफी देर तक काम करता है, जैसा कि आप उम्मीद करेंगे।

मैं इसे कंसोल स्क्रिप्ट प्रविष्टि बिंदुओं के लिए डॉकॉप के साथ उपयोग करता हूं।

0

डालने print __doc__ सिर्फ वर्ग घोषणा के बाद ,, से पहले, कंसोल के लिए डॉक स्ट्रिंग हर बार प्रिंट होगा आप वर्ग के साथ एक वस्तु आरंभ

+0

लेकिन प्रश्न एक समारोह में प्रवेश की रिपोर्ट करना था, न कि कक्षा के तत्काल होने पर। – RufusVS

+0

इसके बारे में क्षमा करें। फिर यह स्वीकार्य उत्तर में होगा। func_name प्रिंट करें .__ doc__ – emorphus

संबंधित मुद्दे