[Python-3000] An introduction to ABC's

Talin talin at acm.org
Sat Apr 14 19:57:28 CEST 2007


Part of the reason why I haven't volunteered to write a PEP for ABC's is 
because I don't feel that I understand the various proposals and the 
background discussion well enough. However, it occurs to me that writing 
the rationale section of a PEP can often be the hardest part, and I 
think I understand the issues well enough to write that preface. So 
here's my contribution:

---

In the domain of object-oriented programming, the usage patterns for 
interacting with an object can be divided into two basic categories, 
which are 'invocation' and 'inspection'.

Invocation means interacting with an object by invoking its methods. 
Usually this is combined with polymorphism, so that invoking a given 
method may run different code depending on the type of an object.

Inspection means the ability for external code (outside of the object's 
methods) to examine the type or properties of that object, and make 
decisions on how to treat that object based on that information.

Both usage patterns serve the same general end, which is to be able to 
support the processing of diverse and potentially novel objects in a 
uniform way, but at the same time allowing processing decisions to be 
customized for each different type of object.

In classical OOP theory, invocation is the preferred usage pattern, and 
inspection is actively discouraged, being considered a relic of an 
earlier, procedural programming style. However, in practice this view is 
simply too dogmatic and inflexible, and leads to a kind of design 
rigidity that is very much at odds with the dynamic nature of a language 
like Python.

In particular, there is often a need to process objects in a way that 
wasn't anticipated by the creator of the object class. It is not always 
the best solution to build in to every object methods that satisfy the 
needs of every possible user of that object. Moreover, there are many 
powerful dispatch philosophies that are in direct contrast to the 
classic OOP requirement of behavior being strictly encapsulated within 
an object, examples being rule or pattern-match driven logic.

On the the other hand, one of the criticisms of inspection by classic 
OOP theorists is the lack of formalisms and the ad hoc nature of what is 
being inspected. In a language such as Python, in which almost any 
aspect of an object can be reflected and directly accessed by external 
code, there are many different ways to test whether an object conforms 
to a particular protocol or not. For example, if asking 'is this object 
a mutable sequence container?', one can look for a base class of 'list', 
or one can look for a method named '__getitem__'. But note that although 
these tests may seem obvious, neither of them are correct, as one 
generates false negatives, and the other false positives.

The generally agreed-upon remedy is to standardize the tests, and group 
them into a formal arrangement. This is most easily done by associating 
with each class a set of standard testable properties, either via the 
inheritance mechanism or some other means. Each test carries with it a 
set of promises: it contains a promise about the general behavior of the 
class, and a promise as to what other class methods will be available.

This PEP proposes a particular strategy for organizing these tests known 
as Abstract Base Classes, or ABC. ABCs are simply Python classes that 
are added into an object's inheritance tree to signal certain features 
of that object to an external inspector. Tests are done using 
isinstance(), and the presence of a particular ABC means that the test 
has passed.

Like all other things in Python, these promises are in the nature of a 
gentlemen's agreement - which means that the language does not attempt 
to enforce that these promises are kept.



More information about the Python-3000 mailing list