[Python-3000] Adaptation [was:Re: Iterators for dict keys, values, and items == annoying :)]

Alex Martelli aleaxit at gmail.com
Mon Apr 3 03:27:31 CEST 2006


On Apr 2, 2006, at 4:39 PM, Walter Dörwald wrote:
 ...
> Why not make the registry identical to the protocol? The protocol 
> is just a convention anyway:

Yes, a 1<->1 relationship between registries and protocols makes the 
'registryof' function I was talking about simpler, at least when it's 
implemented as identity. What's the advantage of this approach, 
compared to allowing protocols to be arbitrary hashable attributes? 
The disadvantage, essentially, is that one gives up the degrees of 
freedom implied by protocols being "just a convention": a protocol 
must now (say) be a callable object exposing a register method (with 
given signature and semantics).
I guess adopting that kind of constraint is OK, as long as the 
constraint doesn't in any way interfere with whatever else Guido 
wants to do with protocols and thus give him a reason to reject 
adaptation. I guess I can see some potential for minor optimization: 
a protocol that's written with some existing types already in mind 
might use a subclass of your 'Adaptor', such as:
class FastTracker(Adaptor):
 def __init__(self, types):
 self.fastrack = set(types)
 Adaptor.__init__(self)
 def _anyof(self, types):
 for t in types:
 if t in self.fastrack: return True
 return False
 def register(self, adaptor, types):
 if self._anyof(types):
 # need better diagnostics here, of course
 raise RegistrationError, "Cannot override identity- 
adaptation"
 return Adaptor.register(self, adaptor, types)
 def __call__(self, obj, *a, **k):
 if self._anyof(type(obj).__mro__):
 if a or k:
 raise ...some kind of diagnostics about a/k not 
allowed here...
 return obj
 return Adaptor.__call__(self, obj, *a, **k)
I'm not sure the advantage is big enough to warrant all the 
machinery, but I can't assert it isn't, either.
>> Isn't it just wonderful, how the foes of adaptation switch horses 
>> on you? First they request a simple-as-dirt, bare-bones 
>> "example system" -- then as soon as you provide one they come 
>> back at you with all sort of "cruft" to be piled on top.
>> I think you might be misinterpreting reactions. If the initial 
> reaction was "I don't understand it. Nobody needs this." (at least 
> that was my reaction), you're "strawman proposal" has put us past 
> this. (At least you got two "I finally got it, this seems useful" 
> from me and Brett.)

You're quite likely right, and I apologize for the misinterpretation; 
I guess I may have misread Brett's desire to hammer adaptation's very 
reason for being down to miniscule smithereens by having the 
existence of some set of methods "imply" identity-adaptation, as a 
subconscious desire to defend against the whole idea of adaptation in 
the guise of sort-of-accepting it, for example.
> So now lets answer the questions: How do we implement adaption of 
> subtypes? What is a protocol? How can we make registration as 
> painless as possible? etc.

Looks like the "loop on __mro__" idea is sort of standard for the 
first of these questions. As for "what is a protocol", I'd rather 
minimize the machinery that goes with it, but I guess that's some 
kind of holdover from the "strawman proposal"; if we're making 
protocols into classes anyway, I'd like to provide them with a 
check_compliance method, taking an object and an integer that 
represents the amount of effort to be spent in the checking -- 0 
meaning 'just check existence of methods', 1 meaning 'check methods' 
signature compatibility too', 2 meaning 'check some semantics at a 
level suitable for fast unit-tests', and so on up. The author of a 
protocol doesn't have to do all that much (levels 0 and 1 can be 
provided by helper functions/methods relying on the inspect module), 
but he or she CAN make the protocol into "an executable 
specification" at whatever level he or she desires. Other error 
checking (e.g., against registration of multiple adapters for one 
protocol/type pair) as well as some modest optimization (mostly of 
adaptation, the frequent case) may also be warranted.
I'm not sure what's painful at all about registration -- at worst 
it's one call per type/protocol pair, some refactoring such as yours 
making it even slighter by allowing the registration of several pairs 
in one call. Do you mean that people are so keen on declarative 
styles that they'd crave, e.g., some special machinery such as
class Duck(object):
 __implements__ = walk, talk, quack
 ...
(with the metaclass doing the registration calls, with identity 
adaptation, under the cover for each protocol in __implements__), 
prizing it highly over explicit:
class Duck(object):
 ...
adapt.register(Duck, (walk, talk, quack), identity)
or the loop or classdecorator version of the latter? Ah well, maybe, 
but most of the discussion sort of smacks to me of AGNI and/or 
premature optimization.
Could we agree that simplicity and even minimalism (with a side order 
of future extensibility if/when warranted) are high on the list of 
desired properties for a protocol adaptation mechanism? After all, 
the more machinery, cruft, and black magic we pile on top of 
adaptation's simple core ideas, the more likely the whole caboodle is 
to provoke allergic reactions in anybody who's not being a part of 
this discussion...
Alex


More information about the Python-3000 mailing list

AltStyle によって変換されたページ (->オリジナル) /