FAQ
Howdy all,

The following is a common idiom::

class FooGonk(object):
def frobnicate(self):
""" Frobnicate this gonk. """
basic_implementation(self.wobble)

class BarGonk(FooGonk):
def frobnicate(self):
special_implementation(self.warble)

The docstring for ?FooGonk.frobnicate? is, intentionally, perfectly
applicable to the ?BarGonk.frobnicate? method also. Yet in overriding
the method, the original docstring is not associated with it.

Ideally there would be a way to specify that the docstring should be
inherited. The best I can come up with is::

class BarGonk(FooGonk):
def frobnicate(self):
special_implementation(self.warble)
frobnicate.__doc__ = FooGonk.frobnicate.__doc__

but that violates DRY (the association between BarGonk and FooGonk is
being repeated), puts the docstring assignment awkwardly after the end
of the method instead of at the beginning where docstrings normally go,
and reads poorly besides.

What is the most Pythonic, DRY-adherent, and preferably least-ugly
approach to override a method, but have the same docstring on both
methods?

--
\ ?Why, I'd horse-whip you if I had a horse.? ?Groucho Marx |
`\ |
_o__) |
Ben Finney

Search Discussions

  • Jean-Paul Calderone at Jul 17, 2009 at 1:13 am

    On Fri, 17 Jul 2009 11:01:49 +1000, Ben Finney wrote:
    Howdy all,

    The following is a common idiom::

    class FooGonk(object):
    def frobnicate(self):
    """ Frobnicate this gonk. """
    basic_implementation(self.wobble)

    class BarGonk(FooGonk):
    def frobnicate(self):
    special_implementation(self.warble)

    The docstring for ?FooGonk.frobnicate? is, intentionally, perfectly
    applicable to the ?BarGonk.frobnicate? method also. Yet in overriding
    the method, the original docstring is not associated with it.

    Ideally there would be a way to specify that the docstring should be
    inherited. The best I can come up with is::

    class BarGonk(FooGonk):
    def frobnicate(self):
    special_implementation(self.warble)
    frobnicate.__doc__ = FooGonk.frobnicate.__doc__

    but that violates DRY (the association between BarGonk and FooGonk is
    being repeated), puts the docstring assignment awkwardly after the end
    of the method instead of at the beginning where docstrings normally go,
    and reads poorly besides.

    What is the most Pythonic, DRY-adherent, and preferably least-ugly
    approach to override a method, but have the same docstring on both
    methods?
    How about this?

    class BarGonk(FooGonk):
    @inherit_docstring
    def frobnicate(self):
    special_implementation(self.warble)

    The implementation of "inherit_docstring" is left as an exercise for the
    reader (it's not utterly trivial, I admit, as "FooGonk" will not readily
    be at hand, but it is still possible).

    By the way, I don't think this is a particularly good idea. Presumably
    there is a reason your implementation is special. It would probably be
    better if this were reflected in the docstring somehow. Perhaps this
    idea is a better one:

    class BarGonk(FooGonk):
    @append_to_docstring
    def frobnicate(self):
    """
    This implementation takes the warble into consideration.
    """
    special_implementation(self.warble)

    With the result of BarGonk.frobnicate.__doc__ being set to:


    Frobnicate this gonk.

    This implementation takes the warble into consideration.

    Jean-Paul
  • Maxim Khitrov at Jul 17, 2009 at 1:21 am

    On Thu, Jul 16, 2009 at 9:13 PM, Jean-Paul Calderonewrote:
    On Fri, 17 Jul 2009 11:01:49 +1000, Ben Finney wrote:

    Howdy all,

    The following is a common idiom::

    ? class FooGonk(object):
    ? ? ? def frobnicate(self):
    ? ? ? ? ? """ Frobnicate this gonk. """
    ? ? ? ? ? basic_implementation(self.wobble)

    ? class BarGonk(FooGonk):
    ? ? ? def frobnicate(self):
    ? ? ? ? ? special_implementation(self.warble)

    The docstring for ?FooGonk.frobnicate? is, intentionally, perfectly
    applicable to the ?BarGonk.frobnicate? method also. Yet in overriding
    the method, the original docstring is not associated with it.

    Ideally there would be a way to specify that the docstring should be
    inherited. The best I can come up with is::

    ? class BarGonk(FooGonk):
    ? ? ? def frobnicate(self):
    ? ? ? ? ? special_implementation(self.warble)
    ? ? ? frobnicate.__doc__ = FooGonk.frobnicate.__doc__

    but that violates DRY (the association between BarGonk and FooGonk is
    being repeated), puts the docstring assignment awkwardly after the end
    of the method instead of at the beginning where docstrings normally go,
    and reads poorly besides.

    What is the most Pythonic, DRY-adherent, and preferably least-ugly
    approach to override a method, but have the same docstring on both
    methods?
    How about this?

    ? class BarGonk(FooGonk):
    ? ? ? @inherit_docstring
    ? ? ? def frobnicate(self):
    ? ? ? ? ? special_implementation(self.warble)

    The implementation of "inherit_docstring" is left as an exercise for the
    reader (it's not utterly trivial, I admit, as "FooGonk" will not readily
    be at hand, but it is still possible).

    By the way, I don't think this is a particularly good idea. ?Presumably
    there is a reason your implementation is special. ?It would probably be
    better if this were reflected in the docstring somehow. ?Perhaps this
    idea is a better one:

    ? class BarGonk(FooGonk):
    ? ? ? @append_to_docstring
    ? ? ? def frobnicate(self):
    ? ? ? ? ? """
    ? ? ? ? ? This implementation takes the warble into consideration.
    ? ? ? ? ? """
    ? ? ? ? ? special_implementation(self.warble)

    With the result of BarGonk.frobnicate.__doc__ being set to:


    ? ?Frobnicate this gonk.

    ? ?This implementation takes the warble into consideration.
    Another way is to use a metaclass. Have its __new__ method loop
    through all attributes and compare those with what is already defined
    in bases. If you find a match, copy the __doc__ attribute. The
    advantage here is that it will work for all methods without any
    additional code, not counting the "__metaclass__ = ..." line. If you
    define a metaclass for the base, then no modifications are required
    for any subclasses. I do agree, however, that the best thing to do is
    to write a very short explanation for what the override is for.

    - Max
  • Rhodri James at Jul 17, 2009 at 1:31 am

    On Fri, 17 Jul 2009 02:01:49 +0100, Ben Finney wrote:

    Howdy all,

    The following is a common idiom::

    class FooGonk(object):
    def frobnicate(self):
    """ Frobnicate this gonk. """
    basic_implementation(self.wobble)

    class BarGonk(FooGonk):
    def frobnicate(self):
    special_implementation(self.warble)

    The docstring for ?FooGonk.frobnicate? is, intentionally, perfectly
    applicable to the ?BarGonk.frobnicate? method also. Yet in overriding
    the method, the original docstring is not associated with it.

    Ideally there would be a way to specify that the docstring should be
    inherited. The best I can come up with is::

    class BarGonk(FooGonk):
    def frobnicate(self):
    special_implementation(self.warble)
    frobnicate.__doc__ = FooGonk.frobnicate.__doc__

    but that violates DRY (the association between BarGonk and FooGonk is
    being repeated),
    Not really. Consider the case of BarGonk being a subclass of FooGonk
    and BazGonk; which docstring would you wish to inherit?
    puts the docstring assignment awkwardly after the end
    of the method instead of at the beginning where docstrings normally go,
    and reads poorly besides.
    Sounds like a job for a decorator!

    (This is probably unbelievably ugly and unwise, since I don't use
    decorators at all often.)

    def copydoc(cls):
    def _fn(fn):
    if fn.__name__ in cls.__dict__:
    fn.__doc__ = cls.__dict__[fn.__name__].__doc__
    return fn
    return _fn

    class BarGonk(FooGonk):
    @copydoc(FooGonk)
    def frobnicate(self):
    special_implementation(self.warble)

    --
    Rhodri James *-* Wildebeest Herder to the Masses
  • Paul McGuire at Jul 17, 2009 at 1:35 am

    On Jul 16, 8:01?pm, Ben Finney wrote:
    Howdy all,

    The following is a common idiom::

    ? ? class FooGonk(object):
    ? ? ? ? def frobnicate(self):
    ? ? ? ? ? ? """ Frobnicate this gonk. """
    ? ? ? ? ? ? basic_implementation(self.wobble)

    ? ? class BarGonk(FooGonk):
    ? ? ? ? def frobnicate(self):
    ? ? ? ? ? ? special_implementation(self.warble)

    The docstring for ?FooGonk.frobnicate? is, intentionally, perfectly
    applicable to the ?BarGonk.frobnicate? method also. Yet in overriding
    the method, the original docstring is not associated with it.

    What is the most Pythonic, DRY-adherent, and preferably least-ugly
    approach to override a method, but have the same docstring on both
    methods?
    Two ideas come to mind, the decorator way and the metaclass way. I am
    not a guru at either, but these two examples work:

    # the decorator way
    def inherit_docstring_from(cls):
    def docstring_inheriting_decorator(fn):
    fn.__doc__ = getattr(cls,fn.__name__).__doc__
    return fn
    return docstring_inheriting_decorator


    class FooGonk(object):
    def frobnicate(self):
    """ Frobnicate this gonk. """
    basic_implementation(self.wobble)


    class BarGonk(FooGonk):
    @inherit_docstring_from(FooGonk)
    def frobnicate(self):
    special_implementation(self.warble)

    bg = BarGonk()
    help(bg.frobnicate)

    Prints:
    Help on method frobnicate in module __main__:

    frobnicate(self) method of __main__.BarGonk instance
    Frobnicate this gonk.


    Using a decorator in this manner requires repeating the super class
    name. Perhaps there is a way to get the bases of BarGonk, but I don't
    think so, because at the time that the decorator is called, BarGonk is
    not yet fully defined.



    # The metaclass way

    from types import FunctionType

    class DocStringInheritor(type):
    def __new__(meta, classname, bases, classDict):
    newClassDict = {}
    for attributeName, attribute in classDict.items():
    if type(attribute) == FunctionType:
    # look through bases for matching function by name
    for baseclass in bases:
    if hasattr(baseclass, attributeName):
    basefn = getattr(baseclass,attributeName)
    if basefn.__doc__:
    attribute.__doc__ = basefn.__doc__
    break

    newClassDict[attributeName] = attribute

    return type.__new__(meta, classname, bases, newClassDict)

    class FooGonk2(object):
    def frobnicate(self):
    """ Frobnicate this gonk. """
    basic_implementation(self.wobble)


    class BarGonk2(FooGonk2):
    __metaclass__ = DocStringInheritor
    def frobnicate(self):
    special_implementation(self.warble)

    bg = BarGonk2()
    help(bg.frobnicate)

    Prints:

    Help on method frobnicate in module __main__:

    frobnicate(self) method of __main__.BarGonk2 instance
    Frobnicate this gonk.


    This metaclass will walk the list of bases until the desired
    superclass method is found AND if that method has a docstring and only
    THEN does it attach the superdocstring to the derived class method.

    Please use carefully, I just did the metaclass thing by following
    Michael Foord's Metaclass tutorial (http://www.voidspace.org.uk/python/
    articles/metaclasses.shtml), I may have missed a step or two.

    -- Paul
  • Ben Finney at Jul 17, 2009 at 2:58 am

    Paul McGuire <ptmcg at austin.rr.com> writes:

    Two ideas come to mind, the decorator way and the metaclass way. I am
    not a guru at either, but these two examples work:
    I think the decorator idea is most attractive to me, since it can be
    applied per method.
    # the decorator way
    def inherit_docstring_from(cls):
    def docstring_inheriting_decorator(fn):
    fn.__doc__ = getattr(cls,fn.__name__).__doc__
    return fn
    return docstring_inheriting_decorator
    That works, thank you.
    Using a decorator in this manner requires repeating the super class
    name. Perhaps there is a way to get the bases of BarGonk, but I don't
    think so, because at the time that the decorator is called, BarGonk is
    not yet fully defined.
    Yes, I tried a few different ways, but within the decorator it seems the
    function object is quite unaware of what class it is destined for.

    --
    \ ?We are human only to the extent that our ideas remain humane.? |
    `\ ?_Breakfast of Champions_, Kurt Vonnegut |
    _o__) |
    Ben Finney
  • Steven D'Aprano at Jul 17, 2009 at 7:52 am

    On Fri, 17 Jul 2009 12:58:48 +1000, Ben Finney wrote:

    Using a decorator in this manner requires repeating the super class
    name. Perhaps there is a way to get the bases of BarGonk, but I don't
    think so, because at the time that the decorator is called, BarGonk is
    not yet fully defined.
    Yes, I tried a few different ways, but within the decorator it seems the
    function object is quite unaware of what class it is destined for.

    When the decorator is called, the function object is just a function
    object, not a method, so there is no concept of "what class it is
    destined for".
    def dec(func):
    ... print type(func)
    ... try:
    ... print func.im_class
    ... except:
    ... print "no im_class"
    ... return func
    ...
    class Test(object):
    ... @dec
    ... def spam(self):
    ... pass
    ...
    <type 'function'>
    no im_class
    type(Test.spam)
    <type 'instancemethod'>
    Test.spam.im_class
    <class '__main__.Test'>


    I suppose you could try to determine what namespace you're currently when
    the class is created, but that's surely going to be fragile and messy.



    --
    Steven
  • David Stanek at Jul 17, 2009 at 12:21 pm

    On Fri, Jul 17, 2009 at 3:52 AM, Steven D'Apranowrote:
    On Fri, 17 Jul 2009 12:58:48 +1000, Ben Finney wrote:

    Using a decorator in this manner requires repeating the super class
    name. ?Perhaps there is a way to get the bases of BarGonk, but I don't
    think so, because at the time that the decorator is called, BarGonk is
    not yet fully defined.
    Yes, I tried a few different ways, but within the decorator it seems the
    function object is quite unaware of what class it is destined for.

    When the decorator is called, the function object is just a function
    object, not a method, so there is no concept of "what class it is
    destined for".
    def dec(func):
    ... ? ? print type(func)
    ... ? ? try:
    ... ? ? ? ? ? ? print func.im_class
    ... ? ? except:
    ... ? ? ? ? ? ? print "no im_class"
    ... ? ? return func
    ...
    class Test(object):
    ... ? ? @dec
    ... ? ? def spam(self):
    ... ? ? ? ? ? ? pass
    ...
    <type 'function'>
    no im_class
    type(Test.spam)
    <type 'instancemethod'>
    Test.spam.im_class
    <class '__main__.Test'>


    I suppose you could try to determine what namespace you're currently when
    the class is created, but that's surely going to be fragile and messy.
    It isn't too bad. I got the idea to use the method's enclosing
    scope[1] in my decorator[2] from DecoratorTools. I am working to
    remove it because it make me sad, but it does work.

    [1] http://code.google.com/p/snake-guice/source/browse/snakeguice/decorators.py#51
    [2] http://code.google.com/p/snake-guice/source/browse/snakeguice/decorators.py#58
  • Shai at Jul 23, 2009 at 11:51 pm

    On Jul 17, 10:52?am, Steven D'Aprano <st... at REMOVE-THIS- cybersource.com.au> wrote:

    When the decorator is called, the function object is just a function
    object, not a method, so there is no concept of "what class it is
    destined for".
    ... which points to the better solution: use a descriptor. With the
    doc_inherit decorator defined below, one may write

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

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

    and it appears to work. The code below is a little longish because we
    need to do slightly different things when called for a class and for
    an instance. But there's no need to repeat the parent name, no need
    to look into namespaces (which, as you said, is probably messy and
    fragile), and it seems pretty readable, too.

    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

    Combining docstrings (as suggested by Jean-Paul Calderone), and
    taking proper care of classmethods and staticmethods, are left
    as an exercise to the reader.

    Have fun,
    Shai.

    From http Fri Jul 24 01:57:10 2009
    From: http (Paul Rubin)
    Date: 23 Jul 2009 16:57:10 -0700
    Subject: If Scheme is so good why MIT drops it?
    References: <b0g665llur83sj9dnumktjvnipacj7bgrt@4ax.com>
    <17pco71asfk7d.1kd4oiidz6nqy.dlg@40tude.net>
    <5gi665hk6ggn0a48o7qd4h3p16phe959hc@4ax.com>
    <19d4rlsscvrgw.xu0laoyvg0$.dlg@40tude.net>
    <361bee02-b7aa-4475-968b-db8d88deb8d8@x25g2000prf.googlegroups.com>
    <1cethsrrw8h6k$.9ty7j7u7zovn.dlg@40tude.net>
    <8bbba0b8-073b-4a43-8954-d5fe7b2f40ee@o15g2000yqm.googlegroups.com>
    <uRr9m.6558$ze1.5162@news-server.bigpond.net.au>
    <rNOSPAMon-7C2B71.09362722072009@news.albasani.net>
    <4e05ee59-db96-4bfc-9828-b11374446ac6@e18g2000vbe.googlegroups.com>
    <7xskgobpnv.fsf@ruckus.brouhaha.com>
    <5993d986-cda2-4dd3-b288-69467a68f949@o6g2000yqj.googlegroups.com>
    <7xfxco35g8.fsf@ruckus.brouhaha.com>
    <f3b79b1c-af91-4136-a2ff-b92afd473a2d@e18g2000vbe.googlegroups.com>
    <7xws60p7kk.fsf@ruckus.brouhaha.com>
    <6a3f1211-b551-4012-904c-0ed0a2c9f6f8@o32g2000yqm.googlegroups.com>
    Message-ID: <7x8wifymuh.fsf@ruckus.brouhaha.com>

    Carl Banks <pavlovevidence at gmail.com> writes:
    I don't think the concept of "drivers" applies to user-mode programs.
    For FFI calls you would use an OS thread.
    That's contrary to the hypothesis, isn't it?
    Yeah, it would have been better to say, green threads are ok for most
    typical forms of i/o concurrency, but OS threads are still necessary
    for some things. An FFI call in particular isn't exactly under the
    control of your language's runtime system; it has to be treated
    more like an external program.

    OS thread?switching is much more expensive than green thread
    switching, so it's still preferable to use green threads when
    possible.
    ?The language runtime switches between busy computation threads on
    ?a timer tick.
    This would seem to result in a tradeoff between performance and low-
    latency.
    GHC appears to use a 100 hz timer, which I'd expect to be fast enough
    for interactive applications while still not causing too much cpu
    load. I don't know if it has a way to assign priorities to
    microthreads (e.g. if you have one running your program's GUI) though.

    I don't think either Python or GHC can implement hard-real-time
    latency because they both use stop-the-world garbage collection.
    E.g. in Python, releasing the last reference to a large list or dict
    can take a long time.
    And Paul, if I'm being a little hard on you here, it's not that I'm
    taking issue with your own claim so much as with your dismissal of
    mine.
    Well, the issue was why Python uses native threads pervasively. As
    far as I can tell, it's just an implementation artifact that has no
    really compelling justification.
  • Aahz at Jul 26, 2009 at 3:55 pm
    In article <056f629b-aa63-458a-ae16-ac40a759e446 at h11g2000yqb.googlegroups.com>,
    Shai wrote:
    class DocInherit(object):
    """
    Docstring inheriting method descriptor

    The class itself is also used as a decorator
    """
    Nice! Maybe stick this on the Cookbook?
    --
    Aahz (aahz at pythoncraft.com) <*> http://www.pythoncraft.com/

    "At Resolver we've found it useful to short-circuit any doubt and just
    refer to comments in code as 'lies'. :-)"
    --Michael Foord paraphrases Christian Muirhead on python-dev, 2009-03-22
  • Shai at Jul 28, 2009 at 8:49 pm

    On Jul 26, 6:55?pm, a... at pythoncraft.com (Aahz) wrote:
    Nice! ?Maybe stick this on the Cookbook?
    http://code.activestate.com/recipes/576862/

    Thanks for the suggestion,

    Shai.
  • Peter Otten at Jul 17, 2009 at 6:58 am

    Ben Finney wrote:

    Howdy all,

    The following is a common idiom::

    class FooGonk(object):
    def frobnicate(self):
    """ Frobnicate this gonk. """
    basic_implementation(self.wobble)

    class BarGonk(FooGonk):
    def frobnicate(self):
    special_implementation(self.warble)

    The docstring for ?FooGonk.frobnicate? is, intentionally, perfectly
    applicable to the ?BarGonk.frobnicate? method also. Yet in overriding
    the method, the original docstring is not associated with it.

    Ideally there would be a way to specify that the docstring should be
    inherited. The best I can come up with is::

    class BarGonk(FooGonk):
    def frobnicate(self):
    special_implementation(self.warble)
    frobnicate.__doc__ = FooGonk.frobnicate.__doc__

    but that violates DRY (the association between BarGonk and FooGonk is
    being repeated), puts the docstring assignment awkwardly after the end
    of the method instead of at the beginning where docstrings normally go,
    and reads poorly besides.

    What is the most Pythonic, DRY-adherent, and preferably least-ugly
    approach to override a method, but have the same docstring on both
    methods?
    Just thinking aloud: Write a patch for pydoc that looks up the base-class
    documentation.

    B.f.__doc__ will continue to return None, but

    help(B.f) will show something like

    No documentation available for B.f.

    Help for A.f:
    yadda yadda


    Of course that might be misleading when A.f and B.f are up to something
    completely different...

    Peter
  • Ben Finney at Jul 17, 2009 at 10:03 am

    Peter Otten <__peter__ at web.de> writes:

    Just thinking aloud: Write a patch for pydoc that looks up the
    base-class documentation.
    That doesn't scale; I want the docstring to be discovered by the normal
    interface (the ?__doc__? attribute) by *every* tool that gathers
    docstrings from methods.

    Also, I want to have this behaviour not for every method missing a
    docstring, but only for selected methods.
    Of course that might be misleading when A.f and B.f are up to
    something completely different...
    Exactly.

    --
    \ ?Facts do not cease to exist because they are ignored.? ?Aldous |
    `\ Huxley |
    _o__) |
    Ben Finney
  • David Stanek at Jul 17, 2009 at 12:08 pm

    On Fri, Jul 17, 2009 at 2:58 AM, Peter Ottenwrote:
    Ben Finney wrote:
    Howdy all,

    The following is a common idiom::

    ? ? class FooGonk(object):
    ? ? ? ? def frobnicate(self):
    ? ? ? ? ? ? """ Frobnicate this gonk. """
    ? ? ? ? ? ? basic_implementation(self.wobble)

    ? ? class BarGonk(FooGonk):
    ? ? ? ? def frobnicate(self):
    ? ? ? ? ? ? special_implementation(self.warble)

    The docstring for ?FooGonk.frobnicate? is, intentionally, perfectly
    applicable to the ?BarGonk.frobnicate? method also. Yet in overriding
    the method, the original docstring is not associated with it.

    Ideally there would be a way to specify that the docstring should be
    inherited. The best I can come up with is::

    ? ? class BarGonk(FooGonk):
    ? ? ? ? def frobnicate(self):
    ? ? ? ? ? ? special_implementation(self.warble)
    ? ? ? ? frobnicate.__doc__ = FooGonk.frobnicate.__doc__

    but that violates DRY (the association between BarGonk and FooGonk is
    being repeated), puts the docstring assignment awkwardly after the end
    of the method instead of at the beginning where docstrings normally go,
    and reads poorly besides.

    What is the most Pythonic, DRY-adherent, and preferably least-ugly
    approach to override a method, but have the same docstring on both
    methods?
    Just thinking aloud: Write a patch for pydoc that looks up the base-class
    documentation.

    B.f.__doc__ will continue to return None, but

    help(B.f) will show something like

    ? ?No documentation available for B.f.

    ? ?Help for A.f:
    ? ?yadda yadda


    Of course that might be misleading when A.f and B.f are up to something
    completely different...
    This should never be the case. It violates LSP and would be very confusing to
    readers of the code.
  • Jean-Michel Pichavant at Jul 27, 2009 at 2:05 pm

    Ben Finney wrote:
    Howdy all,

    The following is a common idiom::

    class FooGonk(object):
    def frobnicate(self):
    """ Frobnicate this gonk. """
    basic_implementation(self.wobble)

    class BarGonk(FooGonk):
    def frobnicate(self):
    special_implementation(self.warble)

    The docstring for ?FooGonk.frobnicate? is, intentionally, perfectly
    applicable to the ?BarGonk.frobnicate? method also. Yet in overriding
    the method, the original docstring is not associated with it.

    Ideally there would be a way to specify that the docstring should be
    inherited. The best I can come up with is::

    class BarGonk(FooGonk):
    def frobnicate(self):
    special_implementation(self.warble)
    frobnicate.__doc__ = FooGonk.frobnicate.__doc__

    but that violates DRY (the association between BarGonk and FooGonk is
    being repeated), puts the docstring assignment awkwardly after the end
    of the method instead of at the beginning where docstrings normally go,
    and reads poorly besides.

    What is the most Pythonic, DRY-adherent, and preferably least-ugly
    approach to override a method, but have the same docstring on both
    methods?
    I am using epydoc and if the docstring is present only in the baseclass
    method, it will repeat the docstring for the child methods. So
    basically, there's nothing to do.
    I've also tried within the python interpreter, and it can perfectly
    solve docstring inheritance. So why would you explicitly assign
    docstring to child methods ?

    JM
  • Shai at Jul 27, 2009 at 9:15 pm

    On Jul 27, 5:05?pm, Jean-Michel Pichavant wrote:
    Ben Finney wrote:
    The docstring for ?FooGonk.frobnicate? is, intentionally, perfectly
    applicable to the ?BarGonk.frobnicate? method also. Yet in overriding
    the method, the original docstring is not associated with it.
    I've also tried within the python interpreter, and it can perfectly
    solve docstring inheritance. So why would you explicitly assign
    docstring to child methods ?
    What do you mean by "can perfectly solve docstring inheritance" ?

    After the following,

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

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

    help(Bar.foo) does not display "Frobber" on my interpreter.
  • Jean-Michel Pichavant at Jul 28, 2009 at 9:33 am

    Shai wrote:
    On Jul 27, 5:05 pm, Jean-Michel Pichavant wrote:

    Ben Finney wrote:
    The docstring for ?FooGonk.frobnicate? is, intentionally, perfectly
    applicable to the ?BarGonk.frobnicate? method also. Yet in overriding
    the method, the original docstring is not associated with it.
    I've also tried within the python interpreter, and it can perfectly
    solve docstring inheritance. So why would you explicitly assign
    docstring to child methods ?
    What do you mean by "can perfectly solve docstring inheritance" ?

    After the following,

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

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

    help(Bar.foo) does not display "Frobber" on my interpreter.
    You're right. I must have made some dumb mistake. So interpreters do not
    solve docstring inheritance, Epydoc does.

    JM

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedJul 17, '09 at 1:01a
activeJul 28, '09 at 8:49p
posts17
users11
websitepython.org

People

Translate

site design / logo © 2022 Grokbase