remove assert statement (Was: Re: PEP new assert idiom)

Carl Banks imbosol at aerojockey.com
Mon Nov 8 14:28:25 EST 2004


Gerrit <gerrit at nl.linux.org> wrote in message news:<mailman.6055.1099832572.5135.python-list at python.org>...
> Paul Rubin wrote:
> > "Raymond Hettinger" <vze4rx4y at verizon.net> writes:
> > > Why do you need a statement for this?
> > > IMO, a plain function will do the trick:
> > 
> > I do write such functions sometimes, but using a statement is more
> > natural.  That's why the assert statement exists, for example.
> 
> I think 'assert' being a statement is on Guido's regrets list. exec and
> print are on his regrets list: both should have been a function. I
> think the same holds for assert, although I'm not sure.

I don't recall seeing assert on that list.  Unlike print and exec,
what assert does can't be done by a function.


> > statement is very great, and I find myself doing it all the time
> > thinking I'll clean it up later.  So I think having a statement for
> > runtime checking would be in the correct spirit.
> 
> In my opinion, assert is almost useless. It can sometimes be useful for
> debugging purposes, but beyond that, it isn't. The exception raised by
> 'assert' is always AssertionError. That is a major disadvantage, because
> it's not specific. 

Actually it is, if you use assert correctly.  I'll get to that.


> If a method I'm calling would raise an AssertionError
> is some cases, and I want to catch it, I'm catching too much. Creating a
> new exception-class and raising that one is better because of this.

If you use assert correctly, you either wouldn't want to catch
AssertionError, or you'd want to catch it at a rather high level and
print a message about a bug in the program.


> I don't see the use of a statement like
> "assert isinstance(message, basestring)". 
[snip]

Generally speaking, this is an incorrect use of assert.  I don't
approve of this use of assert.

The proper use of assert is to declare that a certain condition is
impossible.  That is, if the program is bug-free, this condition will
never happen.  An assertion error should never be raised unless
there's a bug in the program.

Here's a ridiculous, and incorrect, but illustrative, example of its
proper use:

    def f(y):
        x = y*y
        assert x >= 0

As we know, multiplying a real number by itself always produces a
positive number (for the sake of argument, let's ignore the fact that
y could be a complex number).  Thus, is it impossible for x to be
negative.  Impossible, that is, unless there's a bug.  The assert
statement declares this to be an impossible condition.  If this
condition does not hold, it can't be bad input.  It's a bug. 
Obviously, this is a silly example, but real world examples aren't so
silly.

Because it's an "impossible" condition, it only needs to be checked in
debugging builds.  This is where the magic of the assert statement
comes in: in an optimized build, the assertion is not checked.  Thus
it's an optimiztion.  If you change assert into a function, Python can
no longer optimize the assertion away, because the function argument
is always evaluated.

This however, raises a question: is it a premature optimization?  I
would say yes and no.  For simple assertion, like assert x >= 0, the
optimization is premature and probably not worth justifying an assert
statement.  However, I still like having it, just to document that the
condition being checked is intended to be an impossible condition, as
opposed to bad input or an operating system error.

However, there are some impossible conditions that are simply not
premature optimizations by anyone's definition.  Let me show you an
example:

    def some_public_function(tree1, tree2):
        assert one-to-one(tree1,tree2)
        ...

In this case, I have two tree heirarchies which the program is to keep
1:1 at all time (i.e., for every node in tree1, there is a
corresponding node in tree2).  There are hundreds of functions
operating on both trees, and all of them have to make sure to update
both hierarchies.  If there is any exit point of a public function
where these trees are not one-to-one, then it's a bug.

The problem is, checking the whole hierarchy every time you call a
public function is simply too expensive for production code.  An
assert statement lets you optimize this call away, and very
conveniently.  I feel that power justifies the existence of assert.

Assert statements have found many, many bugs in my larger projects, so
I would be very sad to see them go away.  HOWEVER, in the end, I could
easily live without it.  Simple assertions don't cost much to check in
production code.  Expensive assertions I usually put in a function
anyways, so I can optimize it away by simply not calling it unless a
debug flag is set.


> In my opinion, assert should be deprecated and then removed in Py3K:
> assertions are redundant, unspecific, and conflict with the philosophy
> of duck typing and EAFP.
> 
> What do others think of this?

I don't want to see it disappear because it has valid uses.

I think it would be wise to discourage the use of assert for purposes
it wasn't intended for, such as the example you gave.

IMO, the best way to do this is to have assertion OFF by default.

The way Python is set up now is to have a default mode and optimized
mode, the optimized mode not running asserts.  I would change that.  I
suggest that Python should instead have a default mode and a debugging
mode, and that assertions should only be checked in debugging mode. 
Ordinary Python runs, without a -g flag, would simply ignore assert
statements.


-- 
CARL BANKS



More information about the Python-list mailing list