In Python how should I test if a variable is None, True or False
I have a function that can return one of three things:
- success (
True
) - failure (
False
) - error reading/parsing stream (
None
)
My question is, if I'm not supposed to test against True
or False
, how should I see what the result is. Below is how I'm currently doing it:
result = simulate(open("myfile"))
if result == None:
print "error parsing stream"
elif result == True: # shouldn't do this
print "result pass"
else:
print "result fail"
is it really as simple as removing the == True
part or should I add a tri-bool data-type. I do not want the simulate
function to throw an exception as all I want the outer program to do with an error is log it and continue.
Solution 1:
if result is None:
print "error parsing stream"
elif result:
print "result pass"
else:
print "result fail"
keep it simple and explicit. You can of course pre-define a dictionary.
messages = {None: 'error', True: 'pass', False: 'fail'}
print messages[result]
If you plan on modifying your simulate
function to include more return codes, maintaining this code might become a bit of an issue.
The simulate
might also raise an exception on the parsing error, in which case you'd either would catch it here or let it propagate a level up and the printing bit would be reduced to a one-line if-else statement.
Solution 2:
Don't fear the Exception! Having your program just log and continue is as easy as:
try:
result = simulate(open("myfile"))
except SimulationException as sim_exc:
print "error parsing stream", sim_exc
else:
if result:
print "result pass"
else:
print "result fail"
# execution continues from here, regardless of exception or not
And now you can have a much richer type of notification from the simulate method as to what exactly went wrong, in case you find error/no-error not to be informative enough.
Solution 3:
Never, never, never say
if something == True:
Never. It's crazy, since you're redundantly repeating what is redundantly specified as the redundant condition rule for an if-statement.
Worse, still, never, never, never say
if something == False:
You have not
. Feel free to use it.
Finally, doing a == None
is inefficient. Do a is None
. None
is a special singleton object, there can only be one. Just check to see if you have that object.
Solution 4:
There are many good answers. I would like to add one more point. A bug can get into your code if you are working with numerical values, and your answer is happened to be 0.
a = 0
b = 10
c = None
### Common approach that can cause a problem
if not a:
print(f"Answer is not found. Answer is {str(a)}.")
else:
print(f"Answer is: {str(a)}.")
if not b:
print(f"Answer is not found. Answer is {str(b)}.")
else:
print(f"Answer is: {str(b)}")
if not c:
print(f"Answer is not found. Answer is {str(c)}.")
else:
print(f"Answer is: {str(c)}.")
Answer is not found. Answer is 0.
Answer is: 10.
Answer is not found. Answer is None.
### Safer approach
if a is None:
print(f"Answer is not found. Answer is {str(a)}.")
else:
print(f"Answer is: {str(a)}.")
if b is None:
print(f"Answer is not found. Answer is {str(b)}.")
else:
print(f"Answer is: {str(b)}.")
if c is None:
print(f"Answer is not found. Answer is {str(c)}.")
else:
print(f"Answer is: {str(c)}.")
Answer is: 0.
Answer is: 10.
Answer is not found. Answer is None.
Solution 5:
I would like to stress that, even if there are situations where if expr :
isn't sufficient because one wants to make sure expr
is True
and not just different from 0
/None
/whatever, is
is to be prefered from ==
for the same reason S.Lott mentionned for avoiding == None
.
It is indeed slightly more efficient and, cherry on the cake, more human readable.
In [1]: %timeit (1 == 1) == True
38.1 ns ± 0.116 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [2]: %timeit (1 == 1) is True
33.7 ns ± 0.141 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)