isinstance() considered harmful

Alex Martelli aleax at aleax.it
Fri Jan 25 13:03:34 CET 2002


"Kragen Sitaker" <kragen at pobox.com> wrote in message
news:mailman.1011910117.27639.python-list at python.org...
    ...
> > I'll talk more about interfaces later.  My question is,
> > are explicit interfaces considered harmful too?
>
> I really like the flexibility in Python that *any* value --- with a
> few exceptions --- can be of any type that implements the right
> interface.  Explicit interfaces could provide this level of
> flexibility, but in Java, they don't.

To provide this level of flexibility, you have to be able to
supply a post-facto adapter for interfaces and classes that
were developed separately, and arrange for it to be used.
This is really needed for implicit interfaces, too, in fact.

Say I have an interface, or its implicit equivalent:
    class kotrable:
        # semantic specs snipped
        def kotr(self): raise NotImplementedError
defined/used in framework X, eg in the crucial function:
    def eat(lotsofstuff):
        for x in lotsofstuff:
            result = x(23)
            result.kotr()
implying each item in lotsofstuff is a callable that,
when called with argument 23, returns a kotrable instance;

and a class defined/generated in framework Y:
    class almostkotrable:
        # mucho stuff snipped
        def practicallykotr(self): print 'almost right'
e.g, with factories such as:
    def afactory(x): return almostkotrable()
    def another(x,y=45):
        if x>y: return None
        else: return almostkotrable()
and so on.

Now, I'd like to call X.eat((Y.afactory, Y.another)) or
something of the kind.  I can't, of course.  I need to
wrap each factory callable in Y into an adapter to
transform the almostkotrable instances into full-fledged
kotrable instances (or convincing ersatzes thereof,
in as much as X doesn't typetest), e.g.:

class myadapter(kotrable, almostkotrable):
    kotr = practicallykotr
    def __init__(self, wrapped):
        self.__dict__ = wrapped.__dict__

def adaptingwrapper(factory):
    def adapted(*args):
        return myadapter(factory(*args))
    return myadapter

and then I can finally code:

X.eat((myadapter(Y.afactory), myadapter(Y.another)))


Unfortunately, not all creational situations lend themselves
to wrapping/adapting so easily.  Wouldn't it be wonderful if,
when framework X needed something respecting its X.kotrable
protocol, it did:

    def eat(lotsofstuff):
        for x in lotsofstuff:
            result = x(23)
            result = adapt(result, kotrable)
            result.kotr()

and I could just register myadapter with the protocol
adaptation framework as the way to have Y.almostkotrable
instances adapted into fully X.kotrable ones?  Ah, what a
bliss it would be...!


This is basically what PEP 246 proposes.  Unfortunately, it
seems to be "just sleeping there", since almost a year.  I
wonder if or how it could be helped along...


Alex






More information about the Python-list mailing list