[Python-3000] Implementations: A syntax for extending method dispatching beyond type/class inheritance

Jim Jewett jimjjewett at gmail.com
Mon Dec 11 23:33:16 CET 2006


On 12/7/06, Dave Anderson <python3000 at davious.org> wrote:
> on 12/3/2006 7:54 PM Bill Janssen wrote:

> > I'm not sure just what this adds over the simple "change_class"
> > function that I've posted twice already.

> I've took a couple passes in the archives, and I haven't found the
> change_class posts yet.  I think you are referring to lying about the
> __class__.  Did I guess correctly?  (Sorry, an archive link would help me.)

No, but look at

http://mail.python.org/pipermail/python-3000/2006-November/004674.html

Note that this avoids creating new objects if they aren't needed, and
keeps the same memory layout (so it is avoids the "can't inherit from
two builtins" problem, and the "can't *really* override str methods"
problems.)

> Has-Method Contracts
> --------------------

> The first thing I loved about python (coming from java), was this
> realization that I was no longer need be caught up in the inheritance
> game.  If I wanted to use an unspoken convention that I could get a
> special string from every object just by defining name() in each of
> those objects, that's all I had to do.  It didn't matter which class
> tree it came from.

This already works, if method name is all you care about.  The people
wanting interfaces want reassurance that the (same-named) method has
the same meaning as the one they're looking for.

You honor an even more subtle version of this distinction by saying
that happening to implement every method doesn't imply implementing
the entire interface.

> Implement (As a) vs Inherit (Is a)
> ----------------------------------

> Basically, if I have some object Car and I want to be able to use it
> like a dict, I don't necessarily consider it inheriting from dict (or
> even UserDict).  That is, I don't think a Car is a dict.

> To me, even if Car happens to represent a dict by being able to be used
> as a dict, the expression of this fact feels better expressed as merely
> implementing dict.

This is a fair request, and is part of why just using Base classes
doesn't feel entirely right.  Whether such a Car should be considered
a dict (or as implementing a dict) is ... something I don't feel like
arguing.  But the differences of opinion are part of why it sometimes
seems that people are talking past each other.

> class Car(dict):        # car... is a dict? hmm, a bad ring to it

vs

> class Car:
>         implements dict # oh, Cars can be used like a dict, got it

> In addition to that subjective differentiation, there is a technical
> argument.  Without something like an implements declaration, if I ever
> want to express a relationship to another class, but with different
> internals, I am forced to first define an abstract class and then
> inherit from that.  With an implements declaration, I can say implements
> dict and be free of inheriting any of its internal implementation.

Not really.  Because dict is implemented in C, with a well-known C
API, you can't really change the internals without breaking at least
a few things.  The number of broken things for dict keeps decreasing,
but for str ... trying to write UserStr suprised me.

> (I concede here that I could, in fact, inherit UserDict, override all
> the methods, and just not call super in my init.)

Go ahead and don't bother to override the 2nd/3rd/etc level functions
-- they may be a bit less efficient, but they'll work.

Or even go ahead and not bother to override the methods that you don't
care about (dangerous, but no worse than lying about what you
implement).

Go ahead and call super in your init.

> Even with the nicely done ABCs, is there an easy way for a class to
> declare that it can be used like a dict with its own implementation of
> dict methods?  With this syntax sketch, UserDict would remain the same
> except:

> class UserDict:
>         implements dict         # dispatch can rely on this declaration
>         ...                     # rather than method-checking
>

    class UserDict(dict): ...

You have to recognize for yourself that the methods are all overridden.

> Btw, if we formally differentiate that I'm declaring an implementation
> (versus inherit and override), I could programatically double-check my
> implementation with tools...
>
> class A:
>         implements Container
>
>         def len(self)
>                 ...

>  >>> interface_compliance(A)

> A implements Container:
>         methods: len
>         missing: get, iterator

You can still write this with base classes.

class Container:
    ...
    def check_compliance(self):
        return (self.__class__.__len__ is not Container.__len__) and ...

-jJ


More information about the Python-3000 mailing list