Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #7343 > unrolled thread

Re: how to inherit docstrings?

Started byCarl Banks <pavlovevidence@gmail.com>
First post2011-06-09 20:36 -0700
Last post2011-06-10 09:51 +0000
Articles 6 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  Re: how to inherit docstrings? Carl Banks <pavlovevidence@gmail.com> - 2011-06-09 20:36 -0700
    Re: how to inherit docstrings? Ben Finney <ben+python@benfinney.id.au> - 2011-06-10 15:18 +1000
      Re: how to inherit docstrings? Ben Finney <ben+python@benfinney.id.au> - 2011-06-10 15:25 +1000
        Re: how to inherit docstrings? Chris Angelico <rosuav@gmail.com> - 2011-06-10 15:39 +1000
    Re: how to inherit docstrings? Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2011-06-10 19:22 +1200
    Re: how to inherit docstrings? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-10 09:51 +0000

#7343 — Re: how to inherit docstrings?

FromCarl Banks <pavlovevidence@gmail.com>
Date2011-06-09 20:36 -0700
SubjectRe: how to inherit docstrings?
Message-ID<943d6cc1-5e1e-4f39-8003-6d70cbbed3a5@glegroupsg2000goo.googlegroups.com>
On Thursday, June 9, 2011 7:37:19 PM UTC-7, Eric Snow wrote:
> When I write ABCs to capture an interface, I usually put the
> documentation in the docstrings there.  Then when I implement I want
> to inherit the docstrings.  Implicit docstring inheritance for
> abstract base classes would meet my needs. 

Do all the subclasses do exactly the same thing?  What's the use of a docstring if it doesn't document what the function does?


class Shape(object):
    def draw(self):
        "Draw a shape"
        raise NotImplementedError

class Triangle(Shape):
    def draw(self):
        print "Triangle"

class Square(Shape):
    def draw(self):
        print "Square"

x = random.choice([Triange(),Square()])
print x.draw.__doc__  # prints "Draws a shape"


Quick, what shape is x.draw() going to draw?  Shouldn't your docstring say what the method is going to do?

So, I'm sorry, but I don't see this being sufficient for your use case for ABCs.


> I'm just not clear on the
> impact this would have for the other use cases of docstrings.

Whenever somebody overrides a method to do something different, the inherited docstring will be insufficient (as in your ABC example) or wrong.  This, I would say, is the case most of the time when overriding a base class method.  When this happens, the language is committing an error.

Put it this way: if Python doesn't automatically inherit docstrings, the worst that can happen is missing information.  If Python does inherit docstrings, it can lead to incorrect information.


Carl Banks

[toc] | [next] | [standalone]


#7350

FromBen Finney <ben+python@benfinney.id.au>
Date2011-06-10 15:18 +1000
Message-ID<87vcweuuvp.fsf@benfinney.id.au>
In reply to#7343
Carl Banks <pavlovevidence@gmail.com> writes:

> On Thursday, June 9, 2011 7:37:19 PM UTC-7, Eric Snow wrote:
> > When I write ABCs to capture an interface, I usually put the
> > documentation in the docstrings there. Then when I implement I want
> > to inherit the docstrings. Implicit docstring inheritance for
> > abstract base classes would meet my needs.
>
> Do all the subclasses do exactly the same thing? What's the use of a
> docstring if it doesn't document what the function does?

The docstring should document the object (module, class, or function) in
a way useful for the user of that API.

Differing implementations don't necessarily make for differing external
behaviour. In those cases where the external behaviour can be adequately
described by exactly the same docstring as the parent class's method,
it's tedious and error-prone to repeat or duplicate the docstring.

> class Shape(object):
>     def draw(self):
>         "Draw a shape"
>         raise NotImplementedError

class Shape(object):
    """ Abstract class for shapes. """

    def draw(self):
        """ Draw this shape. """
        raise NotImplementedError

> class Triangle(Shape):
>     def draw(self):
>         print "Triangle"

class Triangle(Shape):
    """ A three-sided polygon. """

    def draw(self):
        trace_three_sided_polygon()

> class Square(Shape):
>     def draw(self):
>         print "Square"

class Square(Shape):
    """ An equal-sided quadrilateral polygon. """

    def draw(self):
        trace_quadrilateral_with_equal_sides()

> x = random.choice([Triange(),Square()])
> print x.draw.__doc__  # prints "Draws a shape"

x = random.choice([Triangle(), Square()])
print x.draw.__doc__    # => "Draw this shape."

> Quick, what shape is x.draw() going to draw?

print x.__doc__    # => " An equal-sided quadrilateral polygon. "

> Shouldn't your docstring say what the method is going to do?

There's nothing wrong with the docstring for a method referring to the
context within which the method is defined.

> Whenever somebody overrides a method to do something different, the
> inherited docstring will be insufficient (as in your ABC example) or
> wrong.

I hope the above demonstrates that your assertion is untrue. Every
single method on a class doesn't need to specify the full context; a
docstring that requires the reader to know what class the method belongs
to is fine.

-- 
 \         “In any great organization it is far, far safer to be wrong |
  `\          with the majority than to be right alone.” —John Kenneth |
_o__)                                            Galbraith, 1989-07-28 |
Ben Finney

[toc] | [prev] | [next] | [standalone]


#7351

FromBen Finney <ben+python@benfinney.id.au>
Date2011-06-10 15:25 +1000
Message-ID<87r572uujj.fsf@benfinney.id.au>
In reply to#7350
Ben Finney <ben+python@benfinney.id.au> writes:

> class Square(Shape):
>     """ An equal-sided quadrilateral polygon. """

That this docstring is imprecise (it describes any rhombus, not
necessarily a square) is something I hope no-one else notices or draws
attention to.

Oh, darn.

-- 
 \       “The sun never sets on the British Empire. But it rises every |
  `\        morning. The sky must get awfully crowded.” —Steven Wright |
_o__)                                                                  |
Ben Finney

[toc] | [prev] | [next] | [standalone]


#7352

FromChris Angelico <rosuav@gmail.com>
Date2011-06-10 15:39 +1000
Message-ID<mailman.77.1307684379.11593.python-list@python.org>
In reply to#7351
On Fri, Jun 10, 2011 at 3:25 PM, Ben Finney <ben+python@benfinney.id.au> wrote:
> Ben Finney <ben+python@benfinney.id.au> writes:
>
>> class Square(Shape):
>>     """ An equal-sided quadrilateral polygon. """
>
> That this docstring is imprecise (it describes any rhombus, not
> necessarily a square) is something I hope no-one else notices or draws
> attention to.

class Square(Number):
    """ A class designed to confuse the issue arbitrarily. """
    pass

Chris Angelico

[toc] | [prev] | [next] | [standalone]


#7361

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2011-06-10 19:22 +1200
Message-ID<95dv1vFmgrU1@mid.individual.net>
In reply to#7343
Carl Banks wrote:

> x = random.choice([Triange(),Square()])
> print x.draw.__doc__  # prints "Draws a shape"
> 
> Quick, what shape is x.draw() going to draw?

Your debugging code is insufficient. It should include

    print type(x)

and then it will be obvious what shape is going to get
drawn.

-- 
Greg

[toc] | [prev] | [next] | [standalone]


#7370

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-06-10 09:51 +0000
Message-ID<4df1e917$0$29977$c3e8da3$5496439d@news.astraweb.com>
In reply to#7343
On Thu, 09 Jun 2011 20:36:53 -0700, Carl Banks wrote:

> x = random.choice([Triange(),Square()]) print x.draw.__doc__  # prints
> "Draws a shape"
> 
> 
> Quick, what shape is x.draw() going to draw?

That's easy... it will draw a type(x).__name__.

I think this not a terribly convincing argument. I don't particularly see 
how it is very different (worse, or better) from what you can already get 
in Python. If you don't know what x is, you might not know what it will 
do.


>>> assert issubclass(ValueError, Exception)
>>> ValueError.__doc__
'Inappropriate argument value (of correct type).'
>>> Exception.__doc__
'Common base class for all non-exit exceptions.'
>>> from random import choice
>>> x = choice([ValueError, Exception])

Quick, what will x.__doc__ print?



> Shouldn't your docstring
> say what the method is going to do?

But it does say what the method does. It prints a shape, just like the 
docstring says. It might not be a terribly detailed description, but that 
counts as a quality of implementation issue, not a functional bug.


> So, I'm sorry, but I don't see this being sufficient for your use case
> for ABCs.
> 
> 
>> I'm just not clear on the
>> impact this would have for the other use cases of docstrings.
> 
> Whenever somebody overrides a method to do something different, the
> inherited docstring will be insufficient (as in your ABC example) or
> wrong.  This, I would say, is the case most of the time when overriding
> a base class method.  When this happens, the language is committing an
> error.

It's hardly a *language* error if you, the developer, writes an 
incomplete or incorrect docstring.

If you want to argue that the language shouldn't enable a failure mode of 
the developer (namely the use of an incomplete or incorrect docstring), 
well, perhaps you are right. But you are assuming that an inherited 
docstring is necessarily wrong, which is not the case. "Prints a shape", 
as in your above example, is a perfectly acceptable, if minimal, 
docstring. It might not be a *great* docstring, but it's not a wrong one.


> Put it this way: if Python doesn't automatically inherit docstrings, the
> worst that can happen is missing information.  If Python does inherit
> docstrings, it can lead to incorrect information.

This is no different from inheriting any other attribute. If your class 
inherits "attribute", you might get an invalid value unless you take 
steps to ensure it is a valid value. This failure mode doesn't cause us 
to prohibit inheritance of attributes.



-- 
Steven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web