[Python-Dev] PEP 246, redux

Phillip J. Eby pje at telecommunity.com
Thu Jan 13 16:17:49 CET 2005


At 10:35 AM 1/13/05 +0000, Paul Moore wrote:
>Now, a lot of the talk has referred to "implicit" adaptation. I'm
>still struggling to understand how that concept applies in practice,
>beyond the case of adaptation chains - at some level, all adaptation
>is "explicit", insofar as it is triggered by an adapt() call.

It's "implicit" in that the caller of the code that contains the adapt() 
call carries no visible indication that adaptation will take place.


> >   It's *still* not intuitively incorrect to me, but there's a couple
> > things I can think of...
> >
> > (a) After you adapted the path to the file, and have a side-effect of
> > opening a file, it's unclear who is responsible for closing it.
> > (b) The file object clearly has state the path object doesn't have, like
> > a file position.
> > (c) You can't  go adapting the path object to a file whenever you
> > wanted, because of those side effects.
>
>In the context of my example above, I was assuming that C was an
>"interface" (whatever that might be). Here, you're talking about
>adapting to a file (a concrete class), which I find to be a much
>muddier concept.
>
>This is very much a "best practices" type of issue, though. I don't
>see PEP 246 mandating that you *cannot* adapt to concrete classes, but
>I can see that it's a dangerous thing to do.
>
>Even the string->path adaptation could be considered suspect. Rather,
>you "should" be defining an IPath *interface*, with operations such as
>join, basename, and maybe open. Then, the path class would have a
>trivial adaptation to IPath, and adapting a string to an IPath would
>likely do so by constructing a path object from the string. From a
>practical point of view, the IPath interface adds nothing over
>adapting direct to the path class, but for the purposes of clarity,
>documentation, separation of concepts, etc, I can see the value.

This confusion was another reason for the "Duck-Typing Adaptation" 
proposal; it's perfectly fine to take a 'path' class and "duck-type" an 
interface from it: i.e when you adapt to 'path', then if you call 
'basename' on the object, you will either:

1. Invoke a method that someone has claimed is semantically equivalent to 
path.basename, OR

2. Get a TypeError indicating that the object you're using doesn't have 
such an operation available.

In effect, this is the duck-typing version of a Java cast: it's more 
dynamic because it doesn't require you to implement all operations "up 
front", and also because third parties can implement the operations and add 
them, and because you can define abstract operations that can implement 
operations "in terms of" other operations.


>Some mistakes are easier to avoid if you have the correct conceptual
>framework. I suspect that interfaces are the conceptual framework
>which make adaptation fall into place. If so, then PEP 246, and
>adaptation per se, is always going to be hard to reason about for
>people without a background in interfaces.

Exactly, and that's a problem -- so, I think I've invented (or reinvented, 
one never knows) the concept of a "duck interface", that requires no 
special background to understand or use, because (for example) it has no 
inheritance except normal inheritance, and involves no "adapter classes" 
anywhere.  Therefore, the reasoning you already apply to ordinary Python 
classes "just works".  (Versus e.g. the interface-logic of Zope and 
PyProtocols, which is *not* ordinary Python inheritance.)


>Hmm. I think I just disqualified myself from making any meaningful 
>comments :-)

And I just requalified you.  Feel free to continue commenting.  :)



More information about the Python-Dev mailing list