[Python-Dev] PEP 246: lossless and stateless

Phillip J. Eby pje at telecommunity.com
Fri Jan 14 18:28:16 CET 2005


At 08:32 AM 1/14/05 -0800, Guido van Rossum wrote:
>I have no desire to add syntax
>complexities like this to satisfy some kind of theoretically nice
>property.

Whether it's syntax or a decorator, it allows you to create stateless 
adapters without needing to write individual adapter *classes*, or even 
having an explicit notion of an "interface" to adapt to.  That is, it makes 
it very easy to write a "good" adapter; you can do it without even 
trying.  The point isn't to make it impossible to write a "bad" adapter, 
it's to make it more attractive to write a good one.

Also, btw, it's not a "theoretically nice" property.  I just tried making 
PyProtocols 'Adapter' class immutable, and reran PEAK's unit tests, 
exercising over 100 adapter classes.  *Three* had state.  All were trivial 
caching, not per-adapter state.

However, even had they *not* been trivial caching, this suggests that there 
are a *lot* of use cases for stateless adapters, and that means that a 
trivial 'like' decorator can make it very easy to write stateless adapters.

What I'm suggesting is effectively replacing PEP 246's global registry with 
one that can generate a stateless adapter from individual operation 
declarations.  But it can still fall back on __conform__ and __adapt__ if 
there aren't any declarations, and we could also require adapt() to return 
the same adapter instance if an adapter is stateful.


>No, I asked for a real-life example. Just provided one, and I'm
>satisfied that stateful adapters can be useful.

But his example doesn't require *per-adapter* state, just 
per-original-object state.  As long as there's a clean way to support that, 
his example still works -- and in fact it works *better*, because then that 
"rare" case he spoke of will work just fine without even thinking about it.

Therefore, I think we should make it easy for stateful adapters to link 
their state to the adapted object, not the adapter instance.  This better 
matches most people's intuitive mental model of adaptation, as judged by 
the comments of people in this discussion who were new to adaptation.  If 
adapt() promised to return the same (stateful) adapter instance each time, 
then Just's "rare" example would work nicely, without a bug.


>One of my hesitations about adding adapt() and interfaces to the core
>language has always been that it would change the "flavor" of much of
>the Python programming we do and that we'd have to relearn how to
>write good code.

Exactly!  I came up with the monkey typing idea specifically to address 
this very issue, because the PEP discussion has shown that it is hard to 
learn to write good adapters, and very easy to be tempted to write bad 
ones.  If there is a very easy way to write good adapters, then it will be 
more attractive to learn about it.  If you have to do a little bit more to 
get per-object state, and then it's hardest of all to get per-adapter 
state, the model is a good match to the frequency of those use cases.

Even better, it avoids creating the concept of an interface, except that 
you want something "like" a file or a dictionary.  It's the first Python 
"interface" proposal I know of that can actually spell the loose notion of 
"file-like" in a concretely useful way!

I think the concept can be extended slightly to work with stateful 
(per-object) adapters, though I'll have to give it some thought and 
prototyping.


>I don't believe for a second that all stateful adapters
>are bad,

Neither do I.  It's *per-adapter-instance* state that's bad, or at least 
that no good use cases have yet been shown for.  If we can make it easy to 
have *per-adapted-object* state, or guarantee "same-adapter return", then 
that's even better.

For example, if there were a weak reference dictionary mapping objects to 
their (stateful) adapters, then adapt() could always return the same 
adapter instance for a given source object, thus guaranteeing a single state.

Of course, this would also imply that adapt() needs to know that an adapter 
is stateful, so that it doesn't keep around lots of trivial stateless 
adapters.  Thus, there should be a little more effort required to create 
this kind of adapter (i.e., you need to say that it's stateful).

By the way, I've encountered the need for *this* kind of stateful adapter 
more than once;
PyProtocols has a notion of a StickyAdapter, that keeps per-adapted-object 
state, which is sometimes needed because you can't hold on to the "same 
adapter" for some reason.  The StickyAdapter attaches itself to the 
original object, such that when you adapt that object again, you always get 
the same StickyAdapter instance.  In basically all the use cases I found 
where there's a *really* stateful adapter, I'm using a StickyAdapter, not 
trying to have per-adapter-instance state.

So, what I'm suggesting is that we make it ridiculously easy for somebody 
to create adapters that either have no state, or that have "sticky" state, 
and make it obscure at best to create one that has per-adapter-instance 
state, because nobody has yet presented an example of per-adapter-instance 
state that wasn't either 1) clearly abuse or 2) would be problematic if 
adapt() always returned the same adapter instance.



More information about the Python-Dev mailing list