Override a method but inherit the docstring

Maxim Khitrov mkhitrov at gmail.com
Thu Jul 16 21:21:16 EDT 2009


On Thu, Jul 16, 2009 at 9:13 PM, Jean-Paul Calderone<exarkun at divmod.com> wrote:
> On Fri, 17 Jul 2009 11:01:49 +1000, Ben Finney <ben+python at benfinney.id.au>
> 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



More information about the Python-list mailing list