I'd add I often use assert
to specify properties such as loop invariants or logical properties my code should have, much like I'd specify them in formally-verified software.
They serve both the purpose of informing readers, helping me reason, and checking I am not making a mistake in my reasoning. For example :
k = 0for i in range(n): assert k == i * (i + 1) // 2 k += i #do some things
or in more complicated situations:
def sorted(l): return all(l1 <= l2 for l1, l2 in zip(l, l[1:]))def mergesort(l): if len(l) < 2: #python 3.10 will have match - case for this instead of checking length return l k = len(l // 2) l1 = mergesort(l[:k]) l2 = mergesort(l[k:]) assert sorted(l1) # here the asserts allow me to explicit what properties my code should have assert sorted(l2) # I expect them to be disabled in a production build return merge(l1, l2)
Since asserts are disabled when python is run in optimized mode, do not hesitate to write costly conditions in them, especially if it makes your code clearer and less bug-prone