[Python-ideas] Contracts in python -- a report & next steps

Marko Ristin-Kaufmann marko.ristin at gmail.com
Wed Oct 24 06:08:41 EDT 2018


Hi Chris,

For the sake of those of us who REALLY don't feel like diving back
> into the extensive threads on this subject, can you please summarize
> the benefits of having this in the stdlib rather than as a third-party
> library?
>

Certainly. We need a standard approach to contracts as opposed to
third-party libraries for the following technical reasons:
* There is no dependency hell if two packages use different versions of the
same contract library.
* Two packages need to inherit each other's contracts (*e.g.*, one package
defines a class which inherits a base class from a different package and
hence needs to inherit its contracts as well).
* Third-party libraries for testing and static verification need a standard
approach to contracts in order to be usable. Otherwise, the authors of
these libraries (*e.g. *Hypothesis) need to support multiple contrat
libraries (if they could ever bother to support multiple of them).

There are many more, but these are the reasons that I find critical.


> Also - have you benchmarked the performance cost of adding contracts?
> Particularly: if you're planning to contractify the stdlib, what is
> the impact on startup performance?
>

I made some preliminary benchmarks. The source code is available at:
https://github.com/Parquery/icontract/tree/master/benchmarks/startup

Average over ten runs in milliseconds on my machine (Intel(R) Core(TM)
i7-4700MQ CPU @ 2.40GHz, 8 cores, 4 GB RAM):
Duration to import the module functions_100_with_no_contract : 795.59 ±
10.47

Duration to import the module functions_100_with_1_contract : 919.53 ± 61.22
Duration to import the module functions_100_with_5_contracts : 1075.81 ±
59.87
Duration to import the module functions_100_with_10_contracts : 1290.22 ±
90.04

Duration to import the module functions_100_with_1_disabled_contract :
833.60 ± 32.07
Duration to import the module functions_100_with_5_disabled_contracts :
851.31 ± 66.93
Duration to import the module functions_100_with_10_disabled_contracts :
897.90 ± 143.02

Duration to import the module classes_100_with_no_invariant : 843.61 ± 28.21

Duration to import the module classes_100_with_1_invariant : 3409.71 ± 95.78
Duration to import the module classes_100_with_5_invariants : 4005.93 ±
131.97
Duration to import the module classes_100_with_10_invariants : 4801.82 ±
157.56

Duration to import the module classes_100_with_1_disabled_invariant :
885.88 ± 44.24
Duration to import the module classes_100_with_5_disabled_invariants :
912.53 ± 101.91
Duration to import the module classes_100_with_10_disabled_invariants :
963.77 ± 161.76

Please let me know if these are the benchmarks you had in mind or you would
like to see something else. I have neither optimized the code for speed nor
investigated why the performance of class invariants differs so much from
the functions. The important bit for me was that disabling contracts
basically had no impact on import time.

Cheers,
Marko
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20181024/25b59211/attachment.html>


More information about the Python-ideas mailing list