5

For example for the following method signature:

def genClusters(n_clusters, n_nodes, cluster_distribution):

n_clusters should be an integer of more than 1.

n_nodes should be an integer of more than n_clusters

cluster_distribution should be a float between 0 and 1.

Should I use a series of if then raise exception statements to handle the argument parameter bounds?

eg:

def genClusters(n_clusters, n_nodes, cluster_distribution):
    if (cluster_distribution < 0 or cluster_distribution > 1):
        raise ValueError("cluster distribution must be between 0 and 1")
    if n_clusters < 1:
         raise ValueError("n_clusters must be at least 1")
    if n_nodes <= n_clusters:
         raise ValueError("n_nodes must be at least n_clusters")

The second question is whether I should include these exception statements in every method that also calls this one.

For example:

def myFoo(foo, bar, bang):
    clusters = genClusters(foo, bar, bang) 

In this scenario, if foo, bar, or bang don't fit previously defined parameter bounds, an exception will be thrown when genClusters is called. So should I also be throwning exceptions at the start of myFoo?

4
  • What's the alternative?
    – Rufflewind
    Jan 23, 2015 at 2:02
  • @Rufflewind Not using exceptions at all?
    – dwjohnston
    Jan 23, 2015 at 2:28
  • 2
    The alternative is returning an error code, or a boolean success value. Exceptions and error codes are generally the two ways one would do this. Exceptions are probably more convenient. Jan 23, 2015 at 2:49
  • I guess what I'm getting at, is that it seems inconvenient to have a bunch of exception statements at the start of every method.
    – dwjohnston
    Jan 23, 2015 at 2:57

1 Answer 1

6

Say you don't check the input arguments beforehand, and just let the function run its course. Consider this: what's worst that's going to happen? (This is not a rhetorical question.) Is giving it bad input going to:

  • cause the function to fail with another exception somewhere deep in the code?
  • waste a lot of time, then fail midway?
  • do something potentially harmful (e.g. delete your valuable data ...)?
  • return a bogus result?
  • cause a confusing error message?

Take these into consideration carefully. In most scenarios, where performance is not of utmost importance, you really want it to fail early and as loudly as possible, so checking for invalid arguments is generally a good idea (hopefully answers your first question).

This helps debugging and reduces the risk of your code doing something awful. Of course, this can be tedious at times, so if you want a quick approach (useful for prototyping), use assert:

assert 0 <= cluster_distribution <= 1

However, there's no use in doing it twice if it's obvious that another function will do it for you, as it will lead to unnecessary code duplication (hopefully answers your second question).

For example, say you have a (rather useless) function like this:

def square_root(s);
    return math.sqrt(s)

There's no need to check whether s is nonnegative because sqrt does that already. In most "small" functions like this, you won't need to do much input checking. Usually, only "big" functions require explicit input checking like these. In some cases, you can restructure code without explicit checks so that if the inputs are invalid it will fail automatically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.