Wandering Thoughts archives

2023-06-27

Belatedly remembering to use the two expression form of Python's assert

Today I confessed on the Fediverse that I had somehow mentally overwritten what I once knew about Python's assert with a C-like version that I wrote as 'assert(expression)' (which I apparently started doing more than a decade ago). What caused me to notice this was that I was revising some Python code to cope with a new situation, and I decided I wanted to fail in some way if an impossible thing turned out to not be as impossible as I thought. This wasn't an error that should be returned normally, and it wasn't really something I wanted to raise as an assertion, so adding an assert was the easy way.

So at first I wrote 'assert(2 <= n <= 23)', and then in my way deliberately forced the assert to fail to test things. This caused me to change the variable name to make the assert slightly more informational, as 'assert(2 <= disknum <= 23)'. This gave a better clue about what the assert was about, but it didn't say what was wrong. Thinking about how to fix that caused a dim flickering light to appear over my head and sent me off to read the specification of assert, which told me about the two expression version and also reminded me that assert is a statement, not a C-like function call.

(My new use of assert in my code hopefully includes enough information about the surrounding context that I can see what went wrong, if something does. It won't give me everything but these are quick, low-effort checks that I don't expect to ever trigger.)

Now that I've re-discovered this full form of assert, my goal is to use it more often for "this is never expected to happen" safety checks in my code. Putting in a single line of an assert can convert an otherwise mysterious failure (like the famous 'NoneType object has no attribute ...' error) into a more explicit one, and prevent my code going off the rails in cases where it might not fail immediately.

(I know, CPython will strip out these assert statements if we ever run with optimization enabled. We're unlikely to ever do that for these Python programs.)

As a side note, in general Python's syntax allows for both putting unnecessary ()'s around expressions and then not having a space between a statement and an expression. This allows what would normally be 'assert expr' to be transformed into 'assert(expr)', so that it looked like a function call to me. Fortunately there are only a few simple statements that can even be potentially confused this way, and I suspect I'm not likely to imagine 'raise' or 'yield' could be function calls (or 'return').

(You can write some complex statements this way, such as 'if(expr):', but then the ':' makes it clear that you have a statement, not a function call.)

AssertTwoExpressionForm written at 22:26:26;

By day for June 2023: 27; before June; after June.

Page tools: See As Normal.
Search:
Login: Password:

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.