3

I'm not sure how to proceed in the following situation.

say we have a function as so:

def runsATask(codes):
    myDicts = [helperFunc(code) for code in codes]
    for item in myDicts:
        # some logic.

Here's the problem, codes is some iterable and should be either a list or a tuple, ie it should be used as so: runsATask(['code1', 'code2', ... 'codeN']), but sometimes N is 1 and so people could call it mistakenly, like so, runsATask('code1') This code will still run, but later on in the for loop it will crap out because myDicts doesn't have the correct objects in it because the list comprehension that made it iterated over a string rather than a list/tuple.

So should I leave it as it is or would the following be a solution:

def runsATask(codes):
    if not isinstance(codes, (list, tuple)):
        raise Exception("Codes should be a list or a tuple")
    myDicts = [helperFunc(code) for code in codes]
    for item in myDicts:
        # some logic.

I'm not sure which way to go because I hear Python circles say to let callers deal with the issue, but debugging a situation like this can be annoying because the caller would deal with the issue in the for loop and had he been informed way earlier about the wrong parameter being passed, then it would save a lot of wasted time.

2 Answers 2

6

This code

if not isinstance(codes, (list, tuple)):
    raise Exception("Codes should be a list or a tuple")

Is called a Guard Clause, and it's a perfectly valid technique.

The reason you throw an exception here is that (presumably), if codes is not an instance of (list, tuple), then the method has no way to recover (unless you want to return some default value or error code from the method instead).

0

A guard clause is very reasonable, but have you considered whether there a negative to creating a list and inserting codes into it if it is not a list or tuple? If the function can compensate without user interaction that would prevent a fatal exception it should do so as long as it doesn't create a side effect.

3
  • Presumably, the caller can improve their code to make sure that the correct type is always being passed. In a properly-written application, the Exception should never occur. Jan 24, 2014 at 18:58
  • Guard clauses are great, but require both the caller and the callee have a code change. If a compensating change is introduced in the callee the caller doesn't need to change. Less elegant? If I say I will accept only items that fit inside a square shaped hole, and you put through a circle should I abort because you didn't put through a square, or fill in the empty space so long as it will not disturb the end result?
    – Kevin
    Jan 24, 2014 at 19:06
  • Depends on whether or not you can reasonably recover from the error condition in the method. Jan 24, 2014 at 19:07

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.