[Python-3000] Adaption & generic functions [was Generic functions]
Guido van Rossum
guido at python.org
Fri Apr 7 19:36:17 CEST 2006
On 4/5/06, Walter Dörwald <walter at livinglogic.de> wrote:
> But might closes off one route we could take if we're adapting to
> something that must provide more than one function/method (i.e. an
> interface) and we'd like to have the interface and the adaption registry
> be identical. Suppose we're designing a new interface for sequence. A
> sequence must provide getitem() and len() methods. If the adapt(at)ion
> API only used register and adapt methods we could do something like this:
>
>
> class Interface(object):
> class __metaclass__(type):
> def __new__(mcl, name, bases, dict):
> # Give each class it's own registry
> dict["registry"] = {}
> return type.__new__(mcl, name, bases, dict)
>
> @classmethod
> def register(cls, adapter, T):
> cls.registry[T] = adapter
>
> @classmethod
> def adapt(cls, obj):
> for base in type(obj).__mro__:
> try:
> return cls.registry[base](obj)
> except KeyError:
> pass
> raise TypeError("can't adapt %r to %r" % (obj, cls))
>
>
> class Sequence(Interface):
> def getitem(self, index): pass
> def len(self): pass
>
>
> class PythonSeqAsSequence(Sequence):
> def __init__(self, obj):
> self.obj = obj
>
> def getitem(self, index):
> return self.obj[i]
>
> def len(self):
> return len(self.obj)
>
> Sequence.register(PythonSeqAsSequence, list)
>
>
> print Sequence.adapt([1,2,3]).len()
>
>
> But if adapting is done via __call__() we have a problem: Sequence
> already provides a __call__, the constructor. Of course if this worked
>
> print Sequence([1,2,3]).len()
>
> would look much better than
>
> print Sequence.adapt([1,2,3]).len()
>
> but I'm not sure if it's possible to work around the constructor/adapt
> clash.
Using @overloaded functions I would create an explicit class variable
which is the @overloaded adapter rather than trying to make the
interface also *be* the adapter. I would define the Interface class
like this:
class InterfaceMetaclass(type):
# I hate anonymous metaclasses
def __new__(mcl, name, bases, dict):
# Give each class it's own registry
dict["adapter"] = overloaded(None) # set default_function to None
return type.__new__(mcl, name, bases, dict)
class Interface:
__metaclass__ = InterfaceMetaclass
# No need for adapt and register methods here
The registration would then look like this:
Sequence.adapter.register(list)(PythonSeqAsSequence)
and the invocation would look like this:
print Sequence.adapter([1,2,3]).len()
--
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-3000
mailing list