Finally understanding the appeal of 'Interfaces'
I spent a long time not really getting the need for coded, explicit implementations of 'Interfaces', by which I mean things like zope.interface. It didn't help that I generally encountered them as part of very large, complex systems like Zope and Twisted, and they tended to come with a lot of extra magic features, which made the whole idea seem like the sort of thing you only needed if you had to deal with such a beast.
Then, recently, the penny dropped and I finally saw the light. Shorn of complexity and extra features, what Interface implementations give you is an explicit and easily used way to assert and ask 'is-a' questions. Need to find out if this object is a compiled regular expression? Just ask if it supports the ICRegexp interface. What to be accepted as a compiled regular expression? Assert that you support ICRegexp.
(Assuming the best and forging ahead is still the most Pythonic approach, but per my original problem you sometimes do need to know this sort of thing. And per yesterday's entry, requiring inheritance is not the answer, especially if you want to build decoupled systems.)
When I put it this way, it's easy to see why you'd like a basic interface implementation. If you have to test at all, simple 'is-a' tests beat both 'is-a-descendant-of' restrictions and probing for duck typing with its annoyances and ambiguities (cf an earlier entry).
In this view, the important thing is really to have a unique name
(really an object) for each interface, so that you avoid the duck
typing ambiguity. A basic implementation is almost
trivial; treat interfaces as opaque objects, and just register classes
as supporting interfaces and then have an '
that works by analogy to
(This demonstrates the old computer science aphorism that there's no
problem that can't be solved by an extra level of indirection, since
that is basically what this does: it adds a level of indirection to
isinstance(), so that instead of asking 'is this object an instance of
one of these classes', you ask 'is this object an instance of a class
that supports this interface'.)
More complex implementations are of course possible; you could give
the interface objects actual behavior and information, add checks for
basic duck typing compatibility with the interface, make it so that
isinterface() can optionally check to see if the object seems to
implement the interface without having declared it, and so on.
(Sooner or later you end up back at zope.interface.)