Yet Another PEP: Query Protocol Interface or __query__

Clark C. Evans cce at clarkevans.com
Tue Mar 27 11:15:34 CEST 2001


On Mon, 26 Mar 2001, Carlos Ribeiro wrote:
> 6) We can solve (5) using a 'proxy', or 'adapter'.

Ahh, it finally got though my dence skull what you
are proposing -- more of a proxy mechanism, which 
has a further constraint, not only must the expected
methods be mapped, but *only* the expected methos
are to be mapped.

> EXAMPLE
> 
> Assume that we have these protocols:
> 
> a) protocol 'IntegerDivision'
>     supports the __div__() method for integer division
> b) protocol 'FloatDivision'
>     supports the __div__() method for floating point division
> 
> #----------------------------------------------------------------------
> 
> class Protocol:
>    """ empty class that can be used for all protocol adaptation """
>    pass
> 
> def MakeProtocolDefault(protocol_methods, adaptee):
>    """ Returns the default protocol adapter for an object
>        The default uses the same name for all methods in the protocol
>        and in the object instance that is being adapted
>    """
>    p = Protocol()
>    for pm in protocol_methods:
>      om = getattr(adaptee, pm)
>      setattr(p, pm, om)
>    return p
> 
> def MakeProtocol(protocol_methods, object_methods):
>    """ Returns the a protocol adapter for an object, mapping
>        each protocol_method to a object_method
>    """
>    p = Protocol()
>    for pm, om in zip(protocol_methods, object_methods):
>      setattr(p, pm, om)
>    return p
> 
> class Number:
>    """ supports both protocols: 'IntegerDivision' & 'FloatDivision' """
>    def __init__(self, p_value):
>      self.value = p_value
> 
>    def div_int(self, b):
>      # integer division
>      return int(self.value)/int(b)
> 
>    def div_float(self, b):
>      # floating point division
>      return float(self.value)/float(b)
> 
>    def __adapt__(self, protocol):
>      if protocol == 'IntegerDivision':
>        return MakeProtocol(['__div__'], [self.div_int])
>      elif protocol == 'FloatDivision':
>        return MakeProtocol(['__div__'], [self.div_float])
>      else:
>        return None
> 
> #----------------------------------------------------------------------
> 
>  >>> n = Number(2)
>  >>> in = n.__adapt__('IntegerDivision')
>  >>> fn = n.__adapt__('FloatDivision')
>  >>> in/3
> 0
>  >>> fn/3
> 0.66666666666666663
>  >>> n.value = 5
>  >>> fn/3
> 1.6666666666666667
>  >>>
> 
> #----------------------------------------------------------------------

Very Neat. 

;) Clark





More information about the Python-list mailing list