Why?

For now, I'll leave it to proponents of Interfaces to explain why Interfaces are better.

Caveat

@abstractmethod

@abstractproperty

zope.interface

zope.interface.common

IMapping.providedBy({})

False

zope.interface

collections

numbers

Clarity

Vehicle

AVehicle

IVehicle

if isinstance(something, Vehicle)

if IVehicle.providedBy(something)

if IVehicle.implementedBy(Something)

issubclass(Something, Vehicle)

zope.interface

InterfaceClass

providedBy

type

__instancecheck__

__doc__

__module__

__name__

_abc_negative_cache_version

list(IVehicle)

zope.interface.verifyClass

zope.interface.verifyObject

Flexibility

isinstance()

ABCMeta.register

__instancecheck__

type

providedBy

InterfaceClass

>>> from zope.interface.interfaces import Interface, IInterface

>>> IInterface.providedBy(Interface)

True

moduleProvides(IVehicle)

zope.interface

zope.interface

directlyProvides

ABCMeta.register

Adaptation

IVehicle

zope.interface

IHTMLRenderer

renderer = IHTMLRenderer(someObject)



import attr

from zope.interface import implementer

from twisted.python.components import registerAdapter



@implementer(IHTMLRenderer)

@attr.s

class VehicleRenderer(object):

"Render a vehicle as HTML"

vehicle = attr.ib(validator=attr.validator.provides(IVehicle))

def renderHTML(self):

return "<h1>A Great Vehicle %s (%s)</h1>" % (

self.vehicle.make.name,

self.vehicle.model.name)



registerAdapter(VehicleRenderer, IVehicle, IHTMLRenderer)

IHTMLRenderer(someVehicle)

VehicleRenderer(someVehicle)

Conclusion

warning: MyWidget claims to implement IWidget, but doesn't implement a 'doWidgetStuff' method

Why use interfaces ? Especially with Python's new ABCs , is there really a use for them?Some of us Zope Interface fans — names withheld to protect the guilty, although you may feel free to unmask yourselves in the comments if you like — have expressed frustration that ABCs beat out interfaces for inclusion of the standard library. However, I recently explored various mailing lists, Interfaces literature, and blogs, and haven't found a coherent description ofone would prefer interfaces over ABCs. It's no surprise that Zope's interface package is poorly understood, given that nobody has even explained it! In fact, PEP 3119 specifically says It seems that nobody has taken up the challenge.I remember Jim Fulton trying to explain this to me many years ago, at a PyCon in Washington DC. I definitely didn't understand it then. I was reluctant to replace the crappy little interfaces system in Twisted at the time with something big and complicated-looking. Luckily the other Twisted committers prevailed upon me, and Zope Interface has saved us from maintaining that misdesigned and semi-functional mess.During that explanation, I remember that Jim kept saying that interfaces provided a model to "reason about intent". At the time I didn't understand why you'd want to reason about intent in code. Wouldn't the docstrings and the implementation specify the intent clearly enough? Now, I can see exactly what he's talking about and I use the features he was referring to all the time. I don't know how I'd write large Python programs without them.This isn't a rant against ABCs. I think ABCs are mostly pretty good, certainly an improvement over what was (or rather, wasn't) there before. ABCs provide things that Interfaces don't, like the newanddecorators. Plus, one of the irritating things about usingis that the metadata about standard objects inis not hooked up to anything:returns. ABCs will provide that metadata in the standard library, makingthat much more useful once it has been upgraded to understand the declarations that theandmodules provide.So, on to the main event: what do Zope Interfaces provide which makes them so great?Let's say we have an idea of something called a "vehicle". We can represent it as one of two things: a real base class (), an ABC () or an Interface ().There are a set of operations that interfaces and base-classes share. We can ask, "is this thing I have a vehicle"? In the base-class case we spell that. In the interfaces case, we say. We can ask, "will instances of this type be a vehicle?". For an interface, we say, and for a base class we say. With the new hooks provided by the ABCs in 2.6 and 3.0, these are almost equivalent. With, you can subclassand write your ownmethod. With the ABC system, you subclassand implementHowever, there are some questions you can't quite cleanly ask of the ABC system. For one thing, what does it reallyto be a Vehicle? If you are looking at AVehicle, you can't tell the difference between implementation details and the specification of the interface. You can use dir() and ignore a few of the usual suspects —— but what about the quirkier bits? Metaclasses, inherited attributes, and so on? There's probably some way to do it, but I certainly can't figure it out quickly enough to include in this article. In other words, types have two jobs: they might be ABCs, or they might be types, or they might be both, and it's impossible to separate those responsibilities.With an Interface, this question is a lot easier to ask. For a quick look,will give a complete list of all the attributes expected of a vehicle, as strings. If you want more detail, IVehicle.namesAndDescriptions() and Method.getSignatureInfo() will oblige.Since the interface encapsulates only what an object isto be, and no functionality of its own, it's possible for frameworks to inspect them and provide much nicer error messages when objects don't match their expectations.andcan tell you, both for error-reporting and unit-testing purposes, whether an objectlike a proper vehicle or not, without actually trying to drive it around.At the most basic level, interfaces are more flexible because they are objects. ABCs aren't objects, at least in the message-passing smalltalk sense; they are a collection of top-level functions and some rules about how those functions apply to types. If you want to change the answer to, you need to register a type by usingor overridingon a real subclass of. If you want to change the answer to, for example for a unit test, all you need is an object with a providedBy method.Of course, you can do it "for real" with an, but you don'tto. In other words, its semantics are those of a normal method call.Interfaces aren't completely self-contained, of course: there are top-level functions that operate on interfaces, like verifyObject. However, there's an interface to describe what is expected:There's also the issue of who implements what. For example, you might have a plug-in system which requires modules to implement some functionality. Generally speaking, modules are instances of ModuleType, so specifying that all modules implement some type with an ABC is somewhat awkward. With an interface, however, there is a specific facility for this: you put adeclaration at the top of your module.In, there is a very clear conceptual break betweenand. A module mayan interface — i.e. be an object which satisfies that interface at runtime — without there being any object thatthat interface — i.e. is a type whose instances automatically provide it. This distinction comes in handy when avoiding certain things. This distinction exists with ABCs; either you "are a subclass of" a type or you "are an instance of" a type, but the language around it is more awkward and vague, especially since you can be a "virtual instance" or "virtual subclass" now as well.There's also the issue of dynamic proxies. If you have a wrapper which provides security around another object, or transparent remote access to another object, or records method calls (and so on) the wrapper really wants to say that itthe interfaces provided by the object it is wrapping, but the wrapper type does notthose interfaces. In other words, different instances of your wrapper class will actually provide different interfaces. Withyou can declare this via thedeclaration. With ABCs, this is not generally possible becausewill only work on a type.Let's say I have an object that provides. I want to display it somehow — and in today's web-centric world, that probably means "I want to generate some HTML". How do I get from here to there? ABCs don't provide an answer to that question. Interfaces don't do thateither, but they do provide a mechanism which allows you to provide an answer: you canfrom one interface to another.I'm not going to get into the intricacies of exactly how adaptation works in, since it isn't important to understand most of the time. Suffice it to say you can adapt based on specific hooks that are registered, based on the type an object is, or based on what interfaces it provides.The gist of it is that you have some thing that you don't know what it is, and you want an object that provides. The way you express that intent is:If there are no rules for adapting an object like the one you have passed to an IHTMLRenderer, then you will get an exception - which is all that will happen, normally. However, this point of separation between the contract that your code expects and the concrete type that your code ends up actually talking to can be very useful.The larger Zope application server has a rich and complex set of tools for defining which adapter is appropriate in which context, but Twisted has a very simple interface to adaptation. You simply register an adapter, which is a 1-argument callable that takes an object that conforms to some interface or is an instance of some class, and returns an object that provides another interface. Here's how you do it:Now, whenever you do, you'll get aYour code for rendering now doesn't need any special-case knowledge about particular types. It is written to an interface, and it's very easy to figure out which one; it says "IHTMLRenderer" right there. It's also easy to find implementors of that interface; just grep for "implementer.*IHTMLRenderer" or similar. Or, use pydoctor and look at the "known implementations" section for the interface in question.In a super-dynamic language like Python, you don'ta system for explicit abstract interfaces. No compiler is going to shoot you for calling a 'foo' method. But, formal interface definitions serve many purposes. They can function as documentation, as a touchstone for code which wants to clearly report programming errors (""), and a mechanism for indirection when you know what contract your code wants but you don't know what implementation will necessarily satisfy it (adaptation).Even with a standard library mechanism for doing some of these things, Zope Interface remains a highly useful library, and if you are working on a large Python system you should consider augmenting its organization and documentation with this excellent tool.