The problem is that I want to re-use patch
variable a couple of lines of code below in the except
clause (if I have not received an error by the time it has been populated), so returning early leads to some complexity if I use encapsulation.
I fully agree with what Steven D’Aprano is saying in here. He’s hit the nail on the head.
If you use assertions as intended, there should be no concern about the optimizer removing them.
If I start to put write code inside my docstrings and write a parse and executer for it. Should I complain about the -OO option removing docstrings? (no, someone should set me straight)
This thread feels focused on the wrong problem. The issue isn’t the optimizer, the issue is misuse of assertions.
If you use assertions as intended, there should be no concern about the optimizer removing them.
It’s not just you though - it’s every single developer for each dependency in you dependency tree that you need to convince that this ideology is worth adhering to.
I’m very confused - what ideology? The “ideology” that you write code that doesn’t assume language constructs work differently than they are documented as doing? It’s not an ideology to read the language spec and follow it…
The ideology here is: Bugs need to be found and fixed. It doesn’t make a difference where the bug is, we need to fix it. (Ned Batchelder, in his PyCon keynote, pointed out that this is true even of things that aren’t software; notably, our interactions with other people are every bit as important as API calls between programs, and if we mess them up, that’s a bug to be fixed.) When there’s a very common problem across many programmers, it sometimes helps for the language to give hints (see, for example, the SyntaxWarning when you type if txt is "word":
in recent Pythons), but it’s very very rare for the language to be changed in response to buggy usage.
The job of assertions is to be checkable declarations that, conceptually, can’t ever fail. It’s safe to skip them in production because they’ll never fail anyway. Now, we’re flawed programmers and we write flawed code, so sometimes they WILL fail in prod; but at very least, our intent should be that they don’t fail.
So what do you do when a programmer’s intent doesn’t line up with the code that’s been written? You change the code - or file a bug report, if it’s not your code - to improve the code. Assertions can be straight-forwardly replaced with conditional exception raising, thus making the code better.
The ideology we’re following is: The world is a really really messy place, and we’re a team of underpaid janitors trying our best to clean things up. Let’s work together to make the world just a tiny bit tidier.
Rust makes the difference explicit with assert!
and debug_assert!
macros. assert!
always runs, debug_assert!
only runs in non-optimised builds. If we’re uncomfortable just deprecating -O
, something similar could be a fairly viable path forward for Python:
-
assert condition
will always raiseAssertionError
if condition does not hold -
debug_assert condition
by default is a no-op, but functions the same asassert
when run under-X dev
I agree that there’s a nice alternate universe where AssertionError
is a subclass of BaseException
, to discourage use in control flow. Too bad.
Overall, I’d be happy to do nothing here, but it is a shame that I’ve seen a lot of people seed fear into beginners’ minds about assert
because of a flag that maybe <0.01% of Python programmers use. assert
is great. It’s self documenting and ergonomic and helps me make sure my code keeps the invariants I intend it to keep.
I think this is mostly about educating people about when to use assert
and why its usually better to use regular if
-statements for checks which are not assertions (ie. not checking invariants).
IMO, the topic’s suggestion is going in a wrong direction: It tries to avoid educating people by making assert
behave just like a regular if
-statement.
If done, it would be better to make this non-breaking by keeping assert
as it is (i.e. equivalent to Rust’s debug_assert!
) and introduce a new always-firing assert. (For example strict_assert
, or maybe something like assert!
or +assert
to not introduce a new keyword?)
I’d be inclined to use a completely different word for it, to avoid confusion like “asserts might not run, but there’s these special kinds of asserts that will”. Instead, it would be “assertions are things that you can safely skip, and here’s a way to establish contracts that will always be run”.
But if you want that, we already have a way to write it. It’s an if statement and a raise. So you’d have to show that it’s better to abbreviate this in some way.
There’s too much bike-shedding here.
Either stop ignoring asserts or continue status quo.
As mostly an outside observer of this thread, I don’t see the discussion as bikeshedding, but rather exploring the problem space and discussing mechanisms to address the problems presented in the OP and followup discussion. I’m not sure it is fair to simply dismiss at all that on the grounds of “bikeshedding”.
Debating, e.g., the spelling of assert
, -OO
or a hypothetical debug_assert
or strict_assert
proposed by some would be bikeshedding, if not directly relevant to solving the problem but the discussion has focused on the intersection of language behavior, user behavior and how to synchronize the two (which can involve some naming discussion, where relevant to the user assumptions at play here).