[Python-3000] Generic functions

Tim Hochberg tim.hochberg at ieee.org
Tue Apr 4 17:04:34 CEST 2006


Phillip J. Eby wrote:
> At 11:03 PM 4/3/2006, Ian Bicking wrote:
>>>Guido van Rossum wrote:
>>>>>On 4/3/06, Ian Bicking <ianb at colorstudy.com> wrote:
>>>>>>>As an alternative to adaptation, I'd like to propose generic functions.
>>>> I think they play much the same role, except they are much simpler to
>>>>use and think about.
>>>>>>Given that Phillip Eby is another proponent of generic functions I
>>>seriously doubt the latter.
>>> Hm. :)
>> Rather than branch all over the map, let me focus for a moment on a 
> very simple type of generic function - the kind that is essentially 
> equivalent to PEP 246-style adaptation. This will make it easier to 
> see the relationship.
>> In the RuleDispatch package, these simple generic functions are 
> defined using dispatch.on and f.when(), like this:
>> import dispatch
>> @dispatch.on('ob') # name of the argument to dispatch based on
> def pprint(ob):
> """This is a pretty-print function"""
>> @pprint.when(object)
> def pprint(ob):
> print repr(ob)
>> @pprint.when(list)
> def pprint(ob):
> # code for the list case
>> Now, this is exactly equivalent to the much longer code that one 
> would write to define an IPrettyPrintable interface with a pprint() 
> method and adapter classes to define the implementation 
> methods. Yes, it's a convenient example - but it also corresponds to 
> a fairly wide array of problems, that also happen to be a significant 
> number of uses for adaptation.

Rewriting this using "distributed" adapters looks like this:
 >>> pprint = Protocol('pprint')
 >>> @pprint.when(object)
... def pprint_obj(obj):
... print repr(obj)
 >>> @pprint.when(list)
... def pprint_list(obj):
... print 'pretty(%r)' % obj
Pretty similar! Stealing the when decorator cleans up the use of 
copy_reg.pickle rewrite a bit as well. I imagine that where these would 
diverge is when there is more than one argument.
Regards,
-tim
P.S., Here's Protocol. To save a few bytes I've stripped classic class 
support.
class Protocol(object):
 all_protocols = set()
 def __init__(self, name):
 self.name = name
 self.registry = {}
 self.all_protocols.add(self)
 def __repr__(self):
 return "<protocol %r>" % self.name
 __str__ = __repr__
 def __call__(self, obj):
 #~ mro = _get_mro(obj)
 mro = type(obj).__mro__
 for cls in mro:
 adapter = self.registry.get(cls, None)
 if adapter is not None:
 return adapter(obj)
 raise ValueError('adapter not found')
 def register(self, adapter, *types):
 if not callable(adapter):
 raise TypeError("adapters must be callable")
 for t in types:
 self.registry[t] = adapter
 def when(self, *types):
 def decorator(adapter):
 self.register(adapter, *types)
 return adapter
 return decorator


More information about the Python-3000 mailing list

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