[Python-3000] Adaptation vs. Generic Functions
Walter Dörwald
walter at livinglogic.de
Thu Apr 6 07:46:14 CEST 2006
Guido van Rossum wrote:
> On 4/5/06, Walter Dörwald <walter at livinglogic.de> wrote:
>> The problem with this is that it looks in the base protocol only if the
>> the class can't be found in the registry of the subprotocol. This mean
>> that an adapter from the subprotocol might be used, although the base
>> protocol has a "better" adapter (i.e. one whose class that is nearer to
>> real class of the object.
>
> It also doesn't look like it will work right for recursive invocations
> of the adapter by some implementation (as happens to be common for the
> pprint example).
If the protocol was a class instead of an instance we could use the mro
of the protocol:
class MetaInterface(type):
def __new__(mcl, name, bases, dict):
# Give each class it's own registry
cls = type.__new__(mcl, name, bases, dict)
cls.registry = {}
return cls
def register(cls, *types):
def decorator(adapter):
for type in types:
cls.registry[type] = adapter
return decorator
def default(cls, *args, **kwargs):
raise TypeError("can adapt %r to %r" % (args[0], cls))
def __call__(cls, *args, **kwargs):
# Cannot construct protocol instances
# Instead, calling the class triggers adaptation
for basetype in type(args[0]).__mro__:
for baseprotocol in cls.__mro__:
registry = getattr(baseprotocol, "registry", None)
if registry is not None:
adapter = registry.get(basetype)
if adapter is not None:
# Must pass the protocol to the adapter
# so that it can dispath to the right protocol
return adapter(cls, *args, **kwargs)
return cls.default(*args, **kwargs)
class Protocol(object):
__metaclass__ = MetaInterface
# Extensible repr protocol
class xrepr(Protocol):
@classmethod
def default(cls, *args, **kwargs):
return repr(*args, **kwargs)
@xrepr.register(list)
def xrepr_list(protocol, obj):
return "[%s]" % ", ".join(protocol(x) for x in obj)
# Subprotocol that overwrites int/long adaption
class hexrepr(xrepr):
pass
@hexrepr.register(int, long)
def hexrepr_number(protocol, obj):
return hex(obj)
print hexrepr(range(4))
This prints
[0x0, 0x1, 0x2, 0x3]
Servus,
Walter
More information about the Python-3000
mailing list