Reputation: 357
I am working on a validation function. I understand that exceptions are used for errors and unexpected situations, but in the case of a validation function, if a condition is not met inside, I would expect it to return False
instead of an exception.
The thing is that after the validation finishes I need to raise an message window with a message like: "Tool exited because X condition not met"
. My workflow has been to return tuples with the result and message:
(True, Y_message)
or (False, X_condition_not_met)
and then:
a, b = result
if not a:
raise_window(message=b)
However recently I have stumbled upon multiple answers raising a controversy about this issue and I am confused. For example some people say to always go with exceptions: What's the best way to return multiple values from a function in Python? and others say tuples are the way to go Best practice in python for return value on error vs. success.
I would appreciate if someone could point me in the right direction.
Upvotes: 2
Views: 3217
Reputation: 1124070
When validating, the purpose of your function is to tell you if the criteria are met. You expect to get a boolean result; valid or not valid. You'd only throw errors if, say, the inputs to the function are not supported, or some dependency for the validation process itself was not met. In that case, the normal operation of the validator cannot be completed, you cannot return valid or not valid in such cases because there is no way for the validator to make that determination.
You can compare this with isinstance()
or issubclass()
; these two functions test a value against another value. They return True
or False
, and raise exceptions if you give them unsupported input:
>>> isinstance(1, int)
True
>>> isinstance(1, 'foobar')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
Normal operation is validation, giving it unsupported input means no valid or invalid value can be returned and thus warrants an exception.
So, for a validator that returns either a (True, message)
or a (False, message)
tuple, I'd only raise exceptions if there was a problem with the validation process itself, not to indicate the (False, message)
case.
Note that it doesn't matter what your validator returns; if you need to return both a valid / invalid flag and corresponding message (and only the validator can produce that message) then returning a tuple is just fine.
You could return a custom class too:
class ValidationResult(object):
def __init__(self, result, message=''):
self.result = bool(result)
self.message = message
def __nonzero__(self): # Python 2
return self.result
__bool__ = __nonzero__ # Python 3
def __str__(self):
return self.message
then use that as a test:
valid = validation(value)
if not valid:
raise_window(message=str(valid))
Upvotes: 10
Reputation: 15019
Using an exception to indicate invalid data is the idiomatic, canonical, Python solution to this problem. Consider the int()
function, if you pass it invalid data, an exception occurs:
>>>> int('abc')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'abc'
Upvotes: -2