Encapsulation, inheritance and polymorphism
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Wed Jul 18 10:31:37 EDT 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.
--
Steven
More information about the Python-list
mailing list