[Python-3000] Generic functions vs. OO

Gustavo Niemeyer gustavo at niemeyer.net
Fri Nov 24 15:00:37 CET 2006


> Let's see your implementation.  Zope's interface system fails on at
> least points 3 and 5.  And regarding #1, Zope's implementation of the
> basic features I described is an order of magnitude more complex, even
> if you compare *just* its code that implements adaptation and
> interface inheritance, with *all* of my code plus Guido's generic
> function implementation.

Comparing complexity of implementations which offer completely
different end results isn't of great value.  Copying methods
from the interface to the class is trivial, as you're aware
of (it doesn't mean it's a good idea).  Support for partial
implementations may also be easily achieved, but its drawbacks
must be considered as well (how to deal with marker
interfaces, etc).

In any case, here is a silly implementation showing that it's
easily feasible without generic functions.  It's slow, since it
does linear searching, but there are several paths for speed
improvements.

    class InterfaceClass(type):
        def __init__(cls, name, bases, attrs):
            signature = set()
            for base in bases:
                signature.update(base.__signature__)
            for name, attr in attrs.items():
                if name not in ("__module__", "__metaclass__"):
                    if isinstance(attr, UnboundMethodType):
                        attr = attr.im_func
                    signature.add((name, attr))
            cls.__signature__ = frozenset(signature)
    
    class Interface:
        __metaclass__ = InterfaceClass
    
    class AdapterRegistry(object):
        def __init__(self):
            self._adapters = []
    
        def register(self, adapter, iorigin, itarget):
            self._adapters.append((adapter, iorigin.__signature__,
                                   itarget.__signature__))
    
        def adapt(self, obj, iface):
            origin = set()
            for obj_iface in obj.__interfaces__:
                origin.update(obj_iface.__signature__)
            target = iface.__signature__
            if origin.issuperset(target):
                return obj
            for adapter, aorigin, atarget in self._adapters:
                if origin.issuperset(aorigin) and target.issubset(atarget):
                    return adapter(obj)
            return None

That's it.

Here is a tested example:

    class C(Interface):
        def m1(): pass
    class D(Interface):
        m1 = C.m1
        def m2(): pass
    class E(Interface):
        def m3(): pass
    class F(E):
        def m4(): pass

    registry = AdapterRegistry()

    class Foo(object):
        __interfaces__ = [D]

    registry.register(lambda x: "Adapted!", C, E)
	
    foo = Foo()
    print registry.adapt(foo, E) # => "Adapted!"
    print registry.adapt(foo, D) # => foo
    print registry.adapt(foo, F) # => None


> 4. No need to understand interface or adaptation theory to be able
> to use it

Sure.. no need to understand concepts you're not using.  You have
to understand what you *are* using instead.

-- 
Gustavo Niemeyer
http://niemeyer.net


More information about the Python-3000 mailing list