[Python-Dev] Son of PEP 246, redux

Phillip J. Eby pje at telecommunity.com
Thu Jan 13 05:19:32 CET 2005


At 09:57 PM 1/12/05 -0500, Phillip J. Eby wrote:
>     class StringIO:
>
>         def read(self, bytes) implements file.read:
>             # etc...
>
>could be used to indicate the simple case where you are conforming to an 
>existing operation definition.  A third-party definition, of the same 
>thing might look like this:
>
>     def file.read(self: StringIO, bytes):
>         return self.read(bytes)
>
>Assuming, of course, that that's the syntax for adding an implementation 
>to an existing operation.

After some more thought, I think this approach:

1. Might not actually need generic functions to be implemented.  I need to 
think some more about properties and Ka-Ping Yee's abstract method idea, to 
make sure they can be made to work without "real" generic functions, but a 
basic version of this approach should be implementable with just a handful 
of dictionaries and decorators.

2. Can be prototyped in today's Python, whether generic functions are used 
or not (but the decorator syntax might be ugly, and the decorator 
implementations might be hacky)

3. May still have some rough bits with respect to subclassing & Liskov; I 
need to work through that part some more.  My preliminary impression is 
that it might be safe to consider inherited (but not overridden) methods as 
being the same logical operation.  That imposes some burden on subclassers 
to redeclare compatibility on overridden methods, but OTOH would be 
typesafe by default.

4. Might be somewhat more tedious to declare adaptations with, than it 
currently is with tools like PyProtocols.

Anyway, the non-generic-function implementation would be to have 'adapt()' 
generate (and cache!) an adapter class by going through all the methods of 
the target class and then looking them up in its 'implements' registry, 
while walking up the source class' __mro__ to find the most-specific 
implementation for that type (while checking for 
overridden-but-not-declared methods along the way).  There would be no 
__conform__ or __adapt__ hooks needed.

Interestingly, C# requires you to declare when you are intentionally 
overriding a base class method, in order to avoid accidentally overriding a 
new method added to a base class later.  This concept actually contains a 
germ of the same idea, requiring overrides to specify that they still 
conform to the base class' operations.

Maybe this weekend I'll be able to spend some time on whipping up some sort 
of prototype, and hopefully that will answer some of my open 
questions.  It'll also be interesting to see if I can actually use the 
technique directly on existing interfaces and adaptation, i.e. get some 
degree of PyProtocols backward-compatibility.  It might also be possible to 
get backward-compatibility for Zope too.  In each case, the backward 
compatibility mechanism would be to change the adapter/interface 
declaration APIs to be equivalent to assertions about all the operations 
defined in a particular interface, against the concrete class you're 
claiming implements the interface.

However, for both PEAK and Zope, it would likely be desirable to migrate 
any interfaces like "mapping object" to be based off of operations in e.g. 
the 'dict' type rather than rolling their own IReadMapping and such.



More information about the Python-Dev mailing list