Assertions

Steve D'Aprano steve+python at pearwood.info
Thu Sep 21 13:44:59 EDT 2017


On Fri, 22 Sep 2017 02:29 am, Tobiah wrote:

> Are these completely equivalent?
> 
> def foo(thing):
> 
>         assert(thing > 0), "Thing must be greater than zero"
> 
> 
> def foo(thing):
> 
>         if not (thing > 0): raise AssertionError("Thing must be greater than
>         zero")
> 
> 
> Other than the fact that the assertion can be turned off
> with -O?

As I replied to Ned just now, the two may compile to slightly different
byte-code. But (apart from the -O optimization) they ought to be semantically
the same, as far as the interpreter goes. I'd be very surprised if the
byte-code differences were ever more than trivial.

But I don't think they are the same as far as the human reader goes. If you
believe the truism that code is written for other people, and only incidentally
to be run by computers, then I think we should say that the two above are very
different.

The first is an actual assertion. It has to be an assertion, because it uses the
assert keyword!

The second is testing a condition, and if need be, raising an exception. Which
looks like an inappropriate exception. Why AssertionError? It looks like it
ought to be a ValueError.

Assertions aren't merely a synonym for testing a condition and raising an
exception if the condition fails. Assertions have semantics to the human
reader. I wrote a blog post explaining why you should use assertions:

- you want a checked comment;
- you have code that can't possibly fail, unless it does;
- you are testing the program logic;
- you are checking a contract;

and when you should not. By using `assert`, you are signalling your intent to do
one of the above.

http://import-that.dreamwidth.org/676.html

But by using an ordinary `if ... raise AssertionError`, the intention is
ambiguous. If you meant for it to be an assertion, why not use assert? If it is
not an assertion, then AssertionError is probably the wrong exception.

(It is okay in a testing framework, like unittest, but a bad idea in a regular
library or an application. Your end-users should never see an AssertionError.)


The bottom line is, if I saw 

    if not (thing > 0): raise AssertionError(...)

in a code review, I'd probably insist that either it be changed to use `assert`,
or the exception be changed to ValueError, whichever better expresses the
intention of the code.



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list