An Interface in Java or C++ is a fundamental concept which enables one to define components.

An interface is meant to describe a component, including any attributes or methods the component might implement.  Classes of objects may be said to implement an interface if their definition conforms to the specifications defined by the Interface.  In this way, an interface provides the hooks to interact with the object without needing to know the implementation detail.

A component driven design leads to pluggable architectures, where each implementation may be developed, tested or debugged in isolation from the rest of the system. 

The concept of interfaces is already prevalent in Python, although Python did not initially have formal interfaces in its specification.  For example:

  • A "Generator" is a thing which returns a sequence
  • A "Sequence" is a thing which implements a __iter__() method and a next() method
  • A "List" is something that has a __getitem__, __setitem__ and __len__ method, etc.
  • A "List" is a specialisation of a more generic hypothetical "Container" type.

So, if you are a Python developer, how would you know which methods are available for such types?  Of course, Python has some marvellous support for introspection:  dir(obj) or help(obj) is generally all you need.

The use of ABC's in other languages

C++ implements interfaces as Abstract Base Classes (ABC's), where methods declared are pure virtual methods.  This defines what the in-memory object should look like and defines the relative addresses for methods in the virtual method table (or vtable).  An implementation of the interface subclasses the abstract base class, thus inheriting the same vtable, and allows the defined virtual methods to be called by an external program while completely hiding the implementation.  This mechanism is the basis for the COM protocol and various other component frameworks.

Java has a similar concept, but uses a specific Interface language construct, or Abstract classes to accomplish the same thing.

Python ABC's

Unlike C++ or Java, Python is a dynamic language, and nothing about objects is hidden. Because of this, it is unlikely that Python components would ever need to be consumed by external programs in the same way C++ components can be.  However, this does not mean that components are not useful as a way to structure a Python program.

ABC's were added to standard Python in PEP 3119.  The basis for this PEP was that it was hard in some instances to be able to tell the type of a python object by examining it's attributes (**).  The example given is to determine whether something is a "mutable sequence container".  One might look for a __getitem__ attribute, or test isinstance(object, list), but that is not conclusive.  PEP3119 provides a way to overload the isinstance and issubclass functions.

Python ABC's are in no way similar to C++ ABC's or Java Interfaces, and are more aimed at solving some introspection limitations with the Python language than they are aimed at providing a way to implement pluggable components.

Even so, one may use Python ABC's to make a base class which gives an error if one attempts to instantiate it, and one may define subclasses which give errors if all the abstract methods are not implemented. Nevertheless, it is hard to see the point of all this since this is Python and not C++, and mimicing C++ behaviour with regard instantiation does not automatically provide the benefits one might associate with C++ or Java interfaces.

In other words, if pluggable Python components is what you are after, ABC's only provide a part of an answer.

(**) One cannot always tell the sex of a chromasome by examining it's genes...

Zope Interfaces

Zope components (2001) preceded PEP 3119 (2007) by a wide margin.  They do not try to mimic the behaviour of C++ or Java interfaces.  Instead, Zope Interfaces focus on the advantages of components as they would pertain to a Python environment, and implement the infrastructure required to enable component oriented development.

If a class were to advertise that it implements a certain Zope Interface, but does not actually define the methods or attributes declared in the interface definition, this does not materially change the behaviour of the Python class.  No error would be raised if the class were to be instantiated.

Why should it matter after all?  One might argue that an interface is a contract, and if a component says that it implements the contract but does not, awful dire things may happen.  So what?  This is Python! You are in control of the code and you have full introspection of all the objects at any stage.  Nothing is hidden.  Implementing a check that a component implements it's contract(s) is just unnecessary overhead.

If you insist, and don't mind the overhead, Zope does provide zope.component.verify.verifyclass() which can ensure that an ordinary Python class does indeed implement the interfaces it says it does.

More important is the ability to easily replace one component with another, or to extend or adapt existing components, or to find which components implement which contracts,  or to build component factories, or to implement publish/subscribe notifications...

These are the important bits about component oriented architectures which the ZCA implements, and which are much more important in practice than an artificial way of implementing contracts that check for validity.

 In a nutshell

Although one might draw a superficial comparison between Zope Interfaces and ABC's, they are fundamentally different.  Take a look at the following graphic:

 

Clearly, where ABC's depends intrinsically on the inheritence mechanism, Zope Interfaces do not. ABC's are more of an "is a" relationship, while Interfaces are more of a "has a", or rather "implements a" relationship, and so not interfere with normal inheritance.  Although having said that, if a subclass derives from a superclass which implements a Zope interface, the subclass will also implement the same.  There is thus no loss of flexiblity, and ABC's have no benefit over Interfaces.

Where with ABC's one may test whether isinstance(myObject, super), the ZCA lets one test whether myInterface.providedBy(myObject).  Where ABC's allow issubclass(myClass, super), Interfaces allow myInterface.implementedBy(myClass).

In practice, being adjacent rather than a part of the inheritence hierarchy, the ZCA allows for a great deal of flexibility regarding one's design.  A fact which becomes evident particularly when reviewing and refactoring for modularity.

 

Grok 4 Noobs

Interfaces compared to Abstract Bases