[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.
[SNIP]
Regards,
-tim
More information about the Python-3000
mailing list