[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