On 28 November 2017 at 13:36, Nick Coghlan <ncoghlan@gmail.com> wrote:
On 28 November 2017 at 15:41, Steven D'Aprano <steve@pearwood.info> wrote:
On Tue, Nov 28, 2017 at 05:12:36AM +0300, Ivan Pozdeev via Python-ideas wrote:
Unlike C, Python does the aforementioned checks all the time, i.e. it's effectively always in "debug mode".
Apart from -O which disables assertions. But in any case, the best use of assertions is not checking things which the interpreter is going to do anyway, but checking things which the interpreter can not and does not check automatically: your program logic. There is no way that the Python interpreter is going to do this check automatically, unless I write the assertion:
assert 0 <= r < abs(y)
That is copied straight out of one of my functions.
I'll make the same observation I usually do each time one of these threads comes up:
* I'm opposed to making assert substantially different from the way it works now * I'm in favour of adding a new "ensure()" builtin that encapsulates the check-and-raise logic
The reasons I prefer this approach:
- assert is a statement *solely* so that the compiler can optimise it out. If it's not optional, it doesn't need to be a statement any more - if the existing assert statements are left alone, there are no performance or compatibility concerns for folks that rely on the current behaviour - if it's a function, it doesn't need to be called "assert", it can use the more imperative term "ensure" (meaning "ensure this condition is true before continuing") - if it's a function, it can easily be emulated on old versions via compatibility libraries - "ensure() is required, assert is optional" is a better answer to complaints about assertions being optional than suggesting "if cond: raise AssertionError(msg)" as a reasonable alternative to "assert cond, msg" - if it's a function, we get access to all the regular function machinery, so we're not restricted to positional-only arguments the way the assert statement is
My initial proposed behaviour for the function:
def ensure(cond, msg=None, exc_type=RuntimeError): """Raise an exception if the given condition is not true""" if not cond: if msg is None: frame = sys._getframe(1) line = frame.f_lineno modname = frame.f_globals.get("__name__", "<unknown module>") msg = f"Condition not met on line {line:d} in {modname!r}" raise exc_type(msg)
Cheers, Nick.
P.S. No, I'm not offering to write that PEP myself, I'd just be in favour of the idea if someone else were to write it :)
+1 on everything Nick said. Paul