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