पायथन वर्ग की विरासत में इनहेरिट डोकस्ट्रिंग्स


97

मैं पायथन में कुछ क्लास इनहेरिटेंस करने की कोशिश कर रहा हूं। मैं प्रत्येक वर्ग और विरासत में मिली कक्षा को अच्छे डॉकस्ट्रिंग्स के लिए पसंद करता हूँ। इसलिए मुझे विरासत में मिली क्लास के लिए लगता है, मुझे यह पसंद है:

  • बेस क्लास डॉकस्ट्रिंग विरासत में मिली
  • शायद docstring के लिए प्रासंगिक अतिरिक्त दस्तावेज संलग्न करें

क्या इस तरह के डॉकस्ट्रिंग हेरफेर को क्लास इनहेरिटेंस स्थिति में करने का कोई (संभवतः सुरुचिपूर्ण या पाइथोनिक) तरीका है? कैसे कई विरासत के बारे में?


2
मैं जवाब नहीं दे सकता क्योंकि सवाल दुर्भाग्य से बंद था, लेकिन पायथन 3.5 के रूप में, inspect.getdocवंशानुक्रम के पेड़ की खोज करेंगे जब तक कि यह डॉकस्ट्रिंग नहीं पाता।
गेरिट डे

जवाबों:


39

केवल तुम ही नहीं हो! comp.lang.pythonइस बारे में कुछ समय पहले एक चर्चा हुई थी, और एक नुस्खा बनाया गया था। इसे यहां देखें

"""
doc_inherit decorator

Usage:

class Foo(object):
    def foo(self):
        "Frobber"
        pass

class Bar(Foo):
    @doc_inherit
    def foo(self):
        pass 

Now, Bar.foo.__doc__ == Bar().foo.__doc__ == Foo.foo.__doc__ == "Frobber"
"""

from functools import wraps

class DocInherit(object):
    """
    Docstring inheriting method descriptor

    The class itself is also used as a decorator
    """

    def __init__(self, mthd):
        self.mthd = mthd
        self.name = mthd.__name__

    def __get__(self, obj, cls):
        if obj:
            return self.get_with_inst(obj, cls)
        else:
            return self.get_no_inst(cls)

    def get_with_inst(self, obj, cls):

        overridden = getattr(super(cls, obj), self.name, None)

        @wraps(self.mthd, assigned=('__name__','__module__'))
        def f(*args, **kwargs):
            return self.mthd(obj, *args, **kwargs)

        return self.use_parent_doc(f, overridden)

    def get_no_inst(self, cls):

        for parent in cls.__mro__[1:]:
            overridden = getattr(parent, self.name, None)
            if overridden: break

        @wraps(self.mthd, assigned=('__name__','__module__'))
        def f(*args, **kwargs):
            return self.mthd(*args, **kwargs)

        return self.use_parent_doc(f, overridden)

    def use_parent_doc(self, func, source):
        if source is None:
            raise NameError, ("Can't find '%s' in parents"%self.name)
        func.__doc__ = source.__doc__
        return func

doc_inherit = DocInherit 

माता-पिता वर्ग की विधि के डॉकस्ट्रिंग को विरासत में देने के लिए यह एक तरीका है। मुझे लगता है कि कई मामलों में उपयोगी होगा। मैं पूरी कक्षा के लिए डॉकस्ट्रिंग के बारे में अधिक सोच रहा था, जहां मैं विरासत और अपील करना चाहूंगा।
क्रेग मैकक्वीन 5

आह, गच्चा। उस मामले में, अधिकांश डॉक-पीढ़ी पहले से ही आपके लिए है।
जॉन फेमिनाला

36

आप डॉकस्ट्रिंग्स को आसानी से बदल सकते हैं:

class Foo(object):
    """
    Foo Class.
    This class foos around.
    """
    pass

class Bar(Foo):
    """
    Bar class, children of Foo
    Use this when you want to Bar around.
    parent:
    """ 
    __doc__ += Foo.__doc__
    pass

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


16
दरअसल, ज्यादातर डॉक्यूमेंटेशन टूल ऐसा करते हैं। लेकिन अंतर्निहित मदद () फ़ंक्शन नहीं करता है।
मारियोविलास

2
@MarioVilas: शायद यह एक बग है जिसे रिपोर्ट किया जाना चाहिए?
n

स्फिंक्स मुझे ऐसा करने के लिए प्रतीत नहीं होता है, शायद इसलिए कि मेरे माता-पिता "निजी" उर्फ ​​नाम एक अंडरस्कोर से शुरू होते हैं।
ग्रिंगो सुवे

6

विशेष रूप से सुरुचिपूर्ण नहीं, लेकिन सरल और प्रत्यक्ष:

class X(object):
  """This class has a method foo()."""
  def foo(): pass

class Y(X):
  __doc__ = X.__doc__ + ' Also bar().'
  def bar(): pass

अभी:

>>> print Y.__doc__
This class has a method foo(). Also bar().

यदि आप इसे भी करना चाहते हैं Init docstring, तो क्या इसे परिभाषा में करने का कोई तरीका है Y? एक ही रास्ता मैं इसे उपयोग कर रहा है ऐसा करने में सक्षम किया गया है __init__.__doc__ = X.__init__.__doc__ + " Also another param"निम्नलिखित __init__में परिभाषा Yलेकिन यह स्वरूपण के साथ गड़बड़ करने के लिए लगता है, अतिरिक्त जोड़ा रिक्त स्थान के कारण।
एमेजिलबर्ट

5

एक मिश्रित स्टाइल जो विरासत में मिले डॉकस्ट्रिंग सिंटैक्स दोनों को संरक्षित कर सकता है और पसंदीदा ऑर्डर हो सकता है:

class X(object):
  """This class has a method foo()."""
  def foo(): pass

class Y(X):
  """ Also bar()."""
  __doc__ = X.__doc__ + __doc__
  def bar(): pass

एलेक्स के रूप में एक ही उत्पादन के साथ:

>>> print Y.__doc__
This class has a method foo(). Also bar().

पतली बर्फ: डॉकस्ट्रिंग के साथ खेलना आपके मॉड्यूल को python -OOकुछ उम्मीद के साथ अनुपयोगी बना सकता है :

TypeError: cannot concatenate 'str' and 'NoneType' objects

4

मैंने docstring विरासत को संभालने के लिए कुछ सरल, हल्के वजन उपकरण प्रदान करने के लिए custom_inherit लिखा ।

यह विभिन्न प्रकार के डॉकस्ट्रिंग (जैसे Numpy, Google और reST स्वरूपित डोकस्ट्रिंग्स) को मर्ज करने के लिए कुछ अच्छी डिफ़ॉल्ट शैलियों के साथ आता है। आप अपनी स्वयं की शैली भी बहुत आसानी से प्रदान कर सकते हैं।

डॉकस्ट्रिंग वर्गों को ओवरलैप करना बच्चे के अनुभाग को स्थगित कर देगा, अन्यथा उन्हें अच्छे स्वरूपण के साथ मिला दिया जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.