views:

3926

answers:

5

Is there a performance or code maintenance issue with using assert as part of the standard code instead of using it just for debugging purposes?

Is

assert x >= 0, 'x is less then zero'

and better or worse then

if x < 0:
    raise Exception, 'x is less then zero'

Also, is there anyway to set a business rule like if x < 0 raise error that is always checked with out the try, except, finally so, if at anytime throughout the code x is < 0 an error is raised, like if you set assert x < 0 at the start of a function, anywhere within the function where x becomes less then 0 an exception is raised?

+16  A: 

To be able to automatically throw an error when x become less than zero throughout the function. You can use class descriptors. Here is an example:

class ZeroException(Exception):
    pass

class variable(object):
    def __init__(self, value=0):
        self.__x = value

    def __set__(self, obj, value):
        if value < 0:
            raise ZeroException('x is less than zero')

        self.__x  = value

    def __get__(self, obj, objType):
        return self.__x

class MyClass(object):
    x = variable()

>>> m = MyClass()
>>> m.x = 10
>>> m.x -= 20
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "my.py", line 7, in __set__
    raise ZeroException('x is less than zero')
ZeroException: x is less than zero
Nadia Alramli
Although properties are implemented as descriptors, I wouldn't call this an example of using them. This is more an example of properties in and of themselves: http://docs.python.org/library/functions.html#property
Jason Baker
+3  A: 

The only thing that's really wrong with this approach is that it's hard to make a very descriptive exception using assert statements. If you're looking for the simpler syntax, remember you can also do something like this:

class XLessThanZeroException(Exception):
    pass

def CheckX(x):
    if x < 0:
        raise XLessThanZeroException()

def foo(x):
    CheckX(x)
    #do stuff here

Another problem is that using assert for normal condition-checking is that it makes it difficult to disable the debugging asserts using the -O flag.

Jason Baker
+26  A: 

Asserts should be used to test conditions that should never happen. The purpose is to crash early in the case of a corrupt program state.

Exceptions should be used for errors that can conceivably happen, and you should almost always create your own Exception classes.


For example, if you're writing a function to read from a configuration file into a dict, improper formatting in the file should raise a ConfigurationSyntaxError, while you can assert that you're not about to return None.


In your example, if x is a value set via a user interface or from an external source, an exception is best.

If x is only set by your own code in the same program, go with an assertion.

Deestan
+4  A: 

Yes, there are issues. Both performance and functional differences apply.

"assert" statements are removed when the code is optimized.

The Python 2.6.4 Docs state:

The current code generator emits no code for an assert statement when optimization is requested at compile time.

If you optimize your code when deploying to production then those annoying but-it-works-in-dev defects will come to plague you.

Refer to: PYTHONOPTIMIZE and -O -OO

John Mee
A: 

In addition to the other answers, asserts themselves throw exceptions, but only AssertionErrors. From a utilitarian standpoint, assertions aren't suitable for when you need fine grain control over which exceptions you catch.

outis