[Python-Dev] One-line abstractmethod function?

Guido van Rossum guido at python.org
Thu Dec 5 22:33:00 CET 2013


On Thu, Dec 5, 2013 at 1:12 PM, Allen Li <cyberdupo56 at gmail.com> wrote:
> On Thu, Dec 05, 2013 at 10:24:11AM -0800, Guido van Rossum wrote:
>> How would you get the docstrings in? It seems cramming that much on a
>> single line doesn't help readability (even though I agree there is a
>> fair amount of boilerplace).
>
> I was basing my initial suggestion somewhat on collections.namedtuple,
> which doesn't support docstring either.

Not yet. :-) (http://bugs.python.org/issue16669)

> One option would be to simply
> not allow for docstrings, requiring the boilerplate method, the other
> would be to add a parameter for the docstring:
>
> make_abstractmethod(name, arglist, docstring='')
>
> On Thu, Dec 5, 2013 at 2:22 PM, Ethan Furman <ethan at stoneleaf.us> wrote:
>
>> On 12/05/2013 10:56 AM, Alexander Belopolsky wrote:
>>
>>> On Thu, Dec 5, 2013 at 1:24 PM, Guido van Rossum wrote:
>>>
>>>>
>>>> How would you get the docstrings in? [...]
>>>>
>>>
>>> One way to reduce the amount of boilerplate code is to make abstractmethod
>>> to supply raise NotImplementedError body when none is given.  Then you can
>>>  write
>>>
>>> class Foo:
>>>      @abc.abstractmethod
>>>      def do_bar(self):
>>>           """perform bar"""
>>>
>>> The docstring will be required when skipping the body which is probably a
>>> good thing.
>>>
>>
>> How will abstractmethod know its function has no body?
>
> I don't think this is a good idea at all, very magical behavior.  It is
> not intuitive or explicit that an abstractmethod-decorated empty
> function raises NotImplementedError.

Agreed.

> On Thu, Dec 05, 2013 at 03:06:00PM -0500, Brett Cannon wrote:
>> But I would be very leery of this being a default behaviour. Raising
>> NotImplementedError is not necessarily what the default result should be
>> for a method. If you are building a class that supports multiple
>> inheritance you will be calling super().do_bar() almost blindly which, if
>> you are not careful, will raise NotImplementedError and that might not be
>> appropriate. Maybe returning None is more reasonable, maybe raising
>> TypeError. But support a default blindly like this can promote bad
>> practices.
>
> I'm not sure what's considered best practice with super() at the moment.
> super() is dangerous if you don't know what you are doing in
> multi-inheritance design, so I'd consider calling super() blindly is the
> problem here, not raising NotImplementedError.

Actually I think the combination of not knowing what you're doing and
mulitple inheritance is the problem.

> I do think raising
> NotImplementedError is reasonable default behavior for an
> abstractmethod.

When not using multiple inheritance, yes.

> The only two alternatives are doing nothing/pass/return
> None or having actual code in the method.
>
> The former is only useful to silently ignore blind super() calling, the
> latter you would define and decorate the method normally.

Actually if you want to support multiple inheritance of your ABC, your
abstract methods *must* be no-ops (or have some kind of default
behavior that can always be done last).

> On Thu, Dec 05, 2013 at 08:39:05PM +0000, MRAB wrote:
>> An abstract method won't have a body (I'm not counting the docstring).
>>
>> If it _does_ have a body, then it's _not_ an abstract method!
>
> It could have a body, though I would agree it's not commonly used that
> way.  Maybe something like the following (though it's a poor example):
>
> class Printer(metaclass=abc.ABCMeta):
>
>     @abc.abstractmethod
>     def print(self):
>         print("Print done.")
>
> class Foo(Printer):
>
>     def print(self):
>         print('foo')
>         super().print()

That's exactly right.

-- 
--Guido van Rossum (python.org/~guido)


More information about the Python-Dev mailing list