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

Tim Hochberg tim.hochberg at ieee.org
Sat Apr 1 22:02:09 CEST 2006

Alex Martelli wrote:

[SNIP a bunch or erudite stuff.]
> Here is a simple reference implementation of adaptation under all of  
> these simplifying assumptions:
> _global_registry = {}
> def register_adapter(T, P, A, registry=_global_registry):
>      registry[T, P] = A
> def adapt(t, P, registry=_global_registry):
>      return registry[type(t), P]

This is more like it. I suspect that last line has a typo: I think it 
needs a "(t)" appended to it, but that's minor. It's great to see 
someone who knows something about adaption put forward a reference 
implementation that's grockable.

Remarkably, it looks a lot like my implementation that I posted in 
parallel with this. Let's compare:

> # adapters.py
> registry = {}
> def register(adapter, resultdescr, *targetdescrs):
>     for x in targetdescrs:
>         registry[(resultdescr, x)] = adapter
> def find(resultdescr, targetdescr):
>     return registry[(resultdescr, targetdescr)] # fixed type here

There are some superficial differences, but the only substantial 
difference is that I chose to use 'find' to get an adapter, rather than 
to actually do the adaption using adapt. This was a conscious choice, 
driven by my desire to avoid tying targetdescr to concrete types. My 
proposal is dumber, and thus more flexible.

Let me give an example where this would matter based, more or less, on 
real code. I load pairs of numpy arrays from a file. These pairs 
represent imaginary numbers but they may be in several different 
formats: real-imag, mag-angle or db-angle. The format is specified in 
the file and the arrays gets tagged with this format when they are loaded.

Now lets suppose I want to use adaption to handle this. Trying to use 
concrete types is a mess here. However, in the find proposal, I can 
simply punt and use strings:

def register(z_from_ri, "complex_array", ('real_array', 'imag_array'))
def register(z_from_ma, "complex_array", ('mag_array', 'angle_array'))
def register(z_from_dba, "complex_array", ('db_array', 'angle_array'))

def f(a1, a2):
     adapter = adaption.fine("complex_array, (a1.descr, a2.descr))
     z = adapter(a1, a2)

It's also very easy to register a new type if I need to do so. Suppose 
that they add mag, radians. No problem:

def register(z_from_mrad, "complex_array", ('db_array', 'radian_array'))

I've completely punted on any attempt at avoiding collisions. All of 
these names would want to be prefixed, or some other method found, to 
avoid collisions, as you (Alex) already mentioned.

That's my take, FWIW, which is probably not much considering I've never 
tried to use adaption, or at least not that I've noticed, in real life.




More information about the Python-3000 mailing list