Bounds checking

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sat Mar 19 03:33:12 EDT 2011


On Fri, 18 Mar 2011 07:24:33 -0700, Martin De Kauwe wrote:

> Hi,
> 
> if one has a set of values which should never step outside certain
> bounds (for example if the values were negative then they wouldn't be
> physically meaningful) is there a nice way to bounds check? I
> potentially have 10 or so values I would like to check at the end of
> each iteration.

assert all(x >= 0 for x in (a, b, c, d, e, f, g, h, i, j))


> However as the loop is over many years I figured I
> probably want to be as optimal as possible with my check. Any thoughts?
> 
> e.g. this is my solution
> 
> # module contain data
> # e.g. print state.something might produce 4.0 import state as state
> 
> def main():
>     for i in xrange(num_days):
>         # do stuff
> 
>         # bounds check at end of iteration
>         bounds_check(state)

Why don't you do the range check *before* storing it in state? That way 
you can identify the calculation that was wrong, instead of merely 
noticing that at some point some unknown calculation went wrong.


> def bounds_check(state):
>     """ check state values are > 0 """
>     for attr in dir(state):
>         if not attr.startswith('__') and getattr(state, attr) < 0.0:

You're looking at every single attribute, including those of super 
classes, when you only want to check "10 or so" attributes. That's 
probably not wise. At the very least, dir() will be a fairly expensive 
call.

If you insist on checking state *after* the value is stored, instead of 
preventing it from being stored in the first place, it is better to make 
the state object responsible for doing it's own bounds checking. That way 
only the state object needs to be updated when you change those ten 
attributes, instead of some arbitrary number of places scattered all 
throughout your code.


>             print "Error state values < 0: %s" % (attr) 
>             sys.exit()

Python already has a mechanism for printing an error message and exiting: 
raise.

    if condition:
        raise ValueError("attribute %s is negative" % name)

This will still halt the application, but it does so without stomping all 
over normal conventions for command line applications (error messages 
should go to stderr, not stdout; the return result should be non-zero) as 
well as normal conventions for Python code (the caller should be able to 
easily catch the exception -- catching sys.exit can be done, but it is a 
pretty unusual thing to do).


-- 
Steven



More information about the Python-list mailing list