Encapsulation, inheritance and polymorphism

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Jul 18 16:31:37 CEST 2012

On Wed, 18 Jul 2012 09:07:22 -0400, Roy Smith wrote:

>> Keep in mind that assertions are not guaranteed to run. Code like the
>> above is buggy, because if Python is run under the -O (optimize) flag,
>> assertions will be stripped out.
> One could equally say that "code like the above is efficient, because if
> Python is run under the -O (optimize) flag, assertions will be stripped
> out" :-)

You seem to have missed my point. Asserts *should* be used for checks 
which are optional. In this case, the fact that assert is optimized away 
is a feature: you have the added safety of a guard against some 
programming errors, while still being able to optimize that code on 
request. This is what assert is for. You get no argument from me about 
that -- my code is bulging with assertions.

But where you *need* an explicit check to run, assert is not suitable, 
because you cannot control whether or not it will run. The caller, not 
you, controls that, by passing -O to the python interpreter.

If you have a public function or method that can be called by any other 
piece of code, and it has required pre-conditions that need to be checked 
(not necessarily a type-check), then DO NOT USE ASSERT.

If you use assert, then sometimes that pre-condition will not happen, and 
the caller can pass garbage into your function. The pre-condition will be 
violated, and your function will silently go off and do the wrong thing 
without warning.

If you're lucky, your program will fail somewhere else, probably far away 
from where the error actually occurs, and you will merely have to spend 
hours or days trying to debug it.

If you're unlucky, your program won't fail, it will just calculate 
garbage, or otherwise do the wrong thing.

Besides, there is another reason not to use assert: it gives the wrong 
exception. If the error is a type error, you should raise TypeError, not 
ValueError, or ZeroDivisionError, or IndexError, or AssertionError. Using 
assert because it saves a line of code is lazy, sloppy programming.

>> Better is to use explicit type checks and raise an exception yourself:
>>     if not isinstance(x, int):
>>         raise TypeError('expected an int, got %r' % x)
> Maybe, but that's two lines where one does just fine.

But one line (assert) does *not* do just fine under the conditions I am 
talking about.

If you need the check to run, then assert is not suitable, because it is 
not guaranteed to run. It's as simple as that.


More information about the Python-list mailing list