I like this discussion. I'd like to add another theme, namely what should happen when there is an error. (This is prompted by race hazards when performing file system operations.) Suppose fn_a() calls fn_b(), and fn_b() raises an exception. What then should fn_a() do? It may be that this exception has left part or all of the system in an inconsistent (invalid) state. At this level of abstraction, it's not possible to sensibly answer this question. Sometimes the whole system should be stopped. Other times, an invalidation of an object is enough. And sometimes, a rollback of the transaction is what's wanted. Here's a well-known example (overflow exception in Ariane 5), which to me shows that these problems can be very hard to get right. https://en.wikipedia.org/wiki/Cluster_(spacecraft) According to wikipedia (above) this failure resulted in "the first example of large-scale static code analysis by abstract interpretation". I expect that in some situations design-by-contract will help here, by encouraging a focus on providing a more complete specification of behaviour. It would be good to have some real-life Python examples. I'd afraid I don't have any (although I've looked either). -- Jonathan