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

Walter Dörwald walter at livinglogic.de
Sat Apr 1 22:25:29 CEST 2006


Alex Martelli wrote:

> [...]
> So, each entity which we can call a "registration of adaptation" (ROA   for short) is a tuple ( (T, P), A) where:
>     T is a type;
>     P is a unique string identifying a protocol;
>     A is a callable, such that, for any direct instance t of T
> (i.e., one such that type(t) is T), A(t) returns an object (often t   itself, or a wrapper over t) which claims "I satisfy
> all the
> constraints which, together, make up protocol P".  A(t) may also   raise some exception, in which case the adaptation attempt
> fails and   the exception propagates.
>
> [...]
> 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]
>
> [...]
>
> a. protocols may be identified quite arbitrarily (e.g. by unique-  strings), though specific formalizations are also
> perfectly possible   and no doubt offer many advantages (partial error-checking, less   indirectness, ...): there is no
> strict need to formalize interfaces   or protocols in order to add protocol-adaptation to Python
>
> b. the possibility of supplying, consuming and adapting-to protocols   becomes non-invasive thanks to registration
>
> In this simplified outline I've supported *only* registration as the   one and only way to obtain adaptation -- conceptually,
> through the   identity function, registration can indeed serve the purpose,
> although optimizations are quite obviously possible.
>
> [...]

I'm beginning to see your point. Suddenly several things in the stdlib look like they use (or could benefit from) some kind of
adaption:
The pickle protocol uses copy_reg.dispatch_table which adapts an object to the pickle protocol.

The copy module uses __copy__ and __deepcopy__ methods to adapt an object to the copy protocol.

The pprint module uses simple type checks (isinstance(foo, dict), isinstance(foo, tuple), isinstance(foo, list)) and a fall back
to the __repr__() method to adapt an object to some kind of pretty printing protocol.
There are probably other ad-hoc adaptions lurking in the stdlib.

IMHO there are two possible routes:

1) Identify all cases of adaption in the stdlib, implement a version of those modules that use the "real" adaption and see if
the result looks cleaner and more extensible.
2) Implement a self contained adaption module that only does adaption and nothing else and publish it in the cheeseshop. This
should be so simple that every other project that wants to use it, but doesn't want to depend on another package can simply
incorporate it. (I immediate recognized two spots in my own code, where I would use this adaption module).
At the minimum this module should support inheritance of the adapted type, so a simple dict won't work.

Defining an adaptor for the copy protocol might look like this:

@adaptor(Foo, "org.python.copy")
class CopyFoo:
   def __init__(self, foo):
      self.foo = foo
   def copy(self):
      ...
   def deepcopy(self, memo=None):
      ...

Would this be a useful application of class decorators?

Bye,
   Walter Dörwald





More information about the Python-3000 mailing list