[Python-ideas] [Python-Dev] the role of assert in the standard library ?
Steven D'Aprano
steve at pearwood.info
Thu Apr 28 15:49:40 CEST 2011
Tarek Ziadé wrote:
> From what I understood so far, a line with an assert should be
> considered as a dead code if we want the code to behave always the
> same way. I remove dead code in my code...
No. There's a difference between dead code (code that cannot be reached)
and asserts. An assert is a statement of confidence:
"I'm sure that this assertion is true, but I'm not 100% sure, because
bugs do exist. But since I'm *nearly* 100% sure, it is safe to optimize
the assertions away, *if* you are brave enough to run with the -O flag."
If you've ever written the typical defensive pattern:
if a:
do_this()
elif b:
do_that()
elif c:
do_something_else()
else:
# This can never happen.
raise RuntimeError('unexpected error')
then you have a perfect candidate for an assertion:
assert any([a, b, c], 'unexpected error')
You know what they say about things that can never happen: they *do*
happen, more often than you like. An assertion is to check for things
that can never happen. Since it can't happen, it's safe to optimize it
away and not perform the check. But since things that can't happen do
happen (due to logic errors and the presence of unexpected bugs), it's
better to generate a failure immediately, where you perform the check,
rather than somewhere else far distant from the problem, or worse,
returning the wrong result.
Assertions are a case of practicality beats purity: in a perfect world,
we'd always be 100% confident that our code was bug-free and free of any
logic errors, and that our assumptions were perfectly correct. But in
the real world, we can't always be quite so sure, and asserts cover that
middle ground where we're *almost* sure about a condition, but not
entirely. Or perhaps we're merely paranoid. Either way, asserts should
never be something you *rely* on (e.g. checking user input).
Let me give you a real world example: I have some code to calculate the
Pearson's Correlation Coefficient, r. At the end of the function, just
before returning, I assert -1 <= r <= 1. I've run this function
thousands of times, possibly tens of thousands, over periods of months,
without any problems. Last week I got an assertion error: r was
something like 1.00000000000000001 (or thereabouts).
So now I know there's a bug in my code. (Unfortunately, not *where* it
is.) Without the assert, I wouldn't know, because that r would likely
have been used in some larger calculation, without me ever noticing that
it can be out of range.
--
Steven
More information about the Python-ideas
mailing list