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

Phillip J. Eby pje at telecommunity.com
Mon Apr 23 23:25:04 CEST 2007

At 04:52 PM 4/23/2007 -0400, Jim Jewett wrote:
>On 4/23/07, Phillip J. Eby <pje at telecommunity.com> wrote:
>>At 11:43 AM 4/23/2007 -0700, Guido van Rossum wrote:
>> >On 4/23/07, Phillip J. Eby <pje at telecommunity.com> wrote:
>> > >    @abstract
>> > >    def spam(fizz):
>> > >        """This function has no default implementation, and raises
>> > >           a "no applicable methods" error if called..."""
>> >(a) What's the point of having a separate keyword for this, as
>> >opposed to just raising an exception from the body?
>>EIBTI, mainly.  Specifically, it's clear from the beginning that you're
>>looking at an empty function -- i.e., one that *can't* be called
>>successfully except for explicitly registered patterns -- versus one that
>>has a truly "generic" base implementation.
>erm... not to me.  To me it looks like any short function until I look

Which is precisely why @abstract is useful.  Are you saying you *don't* 
want @abstract explicitly indicating that the function has no behavior?

>>I believe there was also another, somewhat more esoteric
>>reason that gets involved when you build more sophisticated
>>rulesystems on top of the base machinery, but the exact reason
>>is escaping me at this moment. ... sort
>>of like doing math without being able to write "zero":
>I think it had to do with next_method, and was the same problem super
>has.  If you aren't sure the job is done -- no matter what you got
>mixed with -- then you have to call the next method.  99% of the time,
>it won't do anything useful, but you have to call it just in case.
>My favorite example is __del__(), or at least close().  I can be sure
>that I've cleaned up *my* scarce resources, but I don't know what
>subclasses might have mixed me in with.  So I call super  __del__, and
>catch the Exception when it turns out I wasn't mixed in at all.
>A "pass" default implementation is much nicer to subclasses than an
>Exception that they have to try...except.

Right.  If you're defining a generic function as a hook, you would just 
define the function as a no-op -- i.e. NOT an @abstract function.  (e.g., 
the "foo()" function in my previous post.)

>> > My point is, I could rename mine to @abstract so that it
>> >would serve your purpose as well -- but only if it would serve.
>>Assuming that:
>>1.  If you call such a function, it will raise some error, like
>Note that your default methods don't do this either, except as part of
>the wrapper.

I don't understand what the sentence above means.  I don't even understand 
it enough to misunderstand it.  :)

>   Guido's current implementation is that
>    (a)  An error is raised as soon as you try to instantiate a class
>that *could* call the method directly, even if you don't plan to ever
>*actually* call it.
>    (b)  The method itself is annotated, so that the rules engine
>could raise an error if it so chose.

Ah.  I'm suggesting that a function object marked as abstract should also 
raise an exception (perhaps NotImplementedError) when it's actually 
called.  @abstract could either change the function object's type, or set 
its func_code, or whatever else makes sense.

>>2.  It's a normal function object (i.e., can have its func_code
>>repointed later)
>>3.  The __isabstractmethod__ can be set back to False once there
>>is other code registered
>I'm not sure that actually *doing* this would play well with ABC
>assumptions, but, yes, it is possible.

Since @overload requires a function of the same name to alread exist in the 
current namespace, you'll normally be doing this:

    class Concrete(Abstract):

        def my_implementation_of_something_abstract(self, ...):
            """Default implementation"""

        def my_implementation_of_something_abstract(self, ...):
            """This overloads *this* class' definition, not the ABC's"""

In any case, I don't really see any reason to add overloads to an ABC's 
abstract methods.  The GF usage of @abstract is really only useful for 
standalone functions, at least as far as I can see.

More information about the Python-3000 mailing list