[Python-3000] Adaptation vs. Generic Functions

Nick Coghlan ncoghlan at gmail.com
Wed Apr 5 16:16:34 CEST 2006


Tim Hochberg wrote:
> I like this version. The naming seems an improvement and the 
> default_adapter seems like a worthy addition. I do keep wondering if 
> there's some reason for a user of Protocol to call candidate_keys 
> directly or it's only an implementation detail. If the there is such a 
> reason, and we could figure it out, it would probably immediately 
> obvious what to call it. If there isn't, perhaps it should be prefixed 
> with '_' to indicate that it's not part of the public interface.

It was a toss-up, but even if it was private, it would still need to be 
documented so subclasses knew how to override it. And if it's public, then it 
might be a useful introspection tool on protocols. For example:

def can_adapt(protocol, *args):
     for key in protocol.candidate_keys(args):
         if key in protocol.registry:
             return True
     return False

Although, now that I think about it, mere presence in the registry doesn't 
necessarily signify much - it's trivial to register an "anti-adapter" that 
raises TypeError. So having this method be public may make it an attractive 
nuisance, rather than something useful. . .

>> # The generic iteration example
>> @GenericFunction
>> def GenericIter(obj):
>>      """This is the docstring for the generic function."""
>>      # The body is the default implementation
>>      if hasattr(obj, "__iter__"):
>>          return obj.__iter__()
>>      raise TypeError("Can't iterate over %s object" % 
>> obj.__class__.__name__)
>>
>> @GenericIter.register(list)
>> def _GenericSequenceIter(obj):
>>      return SequenceIter(obj)
>>
>> GenericIter.register(str)(_GenericSequenceIter)
>> GenericIter.register(unicode)(_GenericSequenceIter)
>>
>> @GenericIter.register(dict)
>> def _GenericDictIter(obj):
>>      return SequenceIter(obj.keys())
>>
> 
> These should all be "GenericIter.register_for", right?

I don't what happened there - I must have hit Ctrl-C instead of Ctrl-V or 
something. . .

That part should have looked like:

@GenericFunction
def GenericIter(obj):
     """This is the docstring for the generic function."""
     # The body is the default implementation
     if hasattr(obj, "__iter__"):
         return obj.__iter__()
     raise TypeError("Can't iterate over %s object" % obj.__class__.__name__)

GenericIter.register(SequenceIter, list, str, unicode)

@GenericIter.register_for(dict)
def _GenericDictIter(obj):
     return SequenceIter(obj.keys())

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://www.boredomandlaziness.org


More information about the Python-3000 mailing list