[Python-3000] Generic function PEP won't make it in time

Guido van Rossum guido at python.org
Tue Apr 24 01:49:52 CEST 2007


On 4/23/07, Phillip J. Eby <pje at telecommunity.com> wrote:
> At 03:16 PM 4/23/2007 -0700, Guido van Rossum wrote:
> >On 4/23/07, Phillip J. Eby <pje at telecommunity.com> wrote:
> >>Assuming that:
> >>
> >>1.  If you call such a function, it will raise some error, like
> >>NotImplementedError
> >
> >That would be up to the author of the function; they would have to
> >explicitly raise NotImplementedError in the body. The ABC proposal
> >allows meaningful abstract methods that can be called (only) via
> >"super"; the use case for this is that the abstract method might be
> >the one that decides which exception should be thrown (e.g.
> >__getitem__ and __next__ do this), or perhaps it could provide a
> >default implementation for certain types. (Potential example of the
> >latter: Sequence.__getitem__() could raise IndexError when the
> >argument is an Integer but handle the case where the argument is a
> >slice instance, assuming there's a suitable factory which could be a
> >designated class method.)
>
> Ah...  interesting.  This is different from what I understood to be
> "abstract" methods in other languages where an abstract method is always
> one that does not have an actual implementation.  I guess I skimmed PEP
> 3119 a little too quickly.
>
> It sounds like your proposal is to mark methods as "abstract" even if they
> have a useful "null" implementation.

Not exactly. Some of the proposed ABCs have concrete methods. These
are the kinds you'd find in mixin classes for Python 2. (Example:
Iterator.__iter__() is a concrete method returning self. You almost
never have a need to override it.) The abstract ones have null
implementations that aren't all that useful for two reasons: (a) they
implement an utter edge case (e.g. an empty iterator) (b) they must be
overridden. Their main purpose is to provide an example -- either they
show which exception to raise (__next__, __getitem__) or they show the
type of value to return (__hash__).

> I guess I don't see what this adds,
> at least for the examples in the sandbox, except for making the class
> non-instantiable as a side-effect.

I guess I exaggerated the usefulness of the null implementations. It's
perfectly fine not to call the null implementation but to inline it
(e.g. raise StopIteration instead of return super(self).__next__()).

> Of course, if @abstract were a class decorator as well as a function
> decorator, then it could have a single meaning in both contexts: "this
> thing shouldn't be callable".
>
> That is to say, this:
>
>     @abstract
>     class Iterator(Iterable):
>         ...
>
> would simply mean calling "Iterator()" would result in a
> NotImplementedError, just like marking a function @abstract means that
> calling it would result in a NotImplementedError.

Yeah, but it would be less specific because (in the case of ABCs that
define multiple methods) it wouldn't tell you which mwethods you have
to override.

> And, as far as I can see, the only ABC method I'd mark @abstract
> individually would be Hashable.__hash__: everything else here looks to me
> like a perfectly valid "empty" implementation of the method(s) in question.

Actually, Hashable.__hash__ is also perfectly valid. :-)

> I suppose there is some value in requiring people to override @abstract
> methods to make a subclass instantiable, versus merely using the lack of an
> @abstract class decorator to indicate that a subclass is concrete.  But I
> wonder if being able to have just one @abstract decorator (that always
> means "you can't call this by default") mightn't be worth giving up that
> tiny bit of extra type checking?

I prefer to follow the lead of C++ here -- an abstract class is
abstract by virtue of having at least one abstract method.

That the abstract methods are still somewhat useful implementations is
mostly to provide a valid (if not necessarily useful) end point for
super-calling in cooperative MI schemes.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-3000 mailing list