45

I think that I fully understand this, but I just want to make sure since I keep seeing people say to never ever test against True, False, or None.

They suggest that routines should raise an error rather than return False or None. Anyway, I have many situations where I simply want to know if a flag is set or not so my function returns True or False. There are other situations where I have a function return None if there was no useful result. From my thinking, neither is problematic so long as I realize that I should never use:

if foo == True
if foo == False
if foo == None

and should instead use:

if foo is True
if foo is False
if foo is None

since True, False, and None are all singletons and will always evaluate the way I expect when using "is" rather than "==". Am I wrong here?

Along the same lines, would it be more Pythonic to modify the functions that sometimes return None so that they raise an error instead?

Say I have an instance method called "get_attr()" that retrieves an attribute from some file. In the case where it finds that the attribute I requested does not exist, is it appropriate to return None? Would it be better to have them raise an error and catch it later?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vorticity
  • 4,582
  • 4
  • 32
  • 49
  • You're only considering the specific case where foo is guaranteed to be a bool. But in general foo could also be (say) an int, so if foo was (say) 7, `if foo == True` would fail, whereas the right test `if foo:` would succeed. – smci Jul 06 '23 at 23:56

9 Answers9

70

The advice isn't that you should never use True, False, or None. It's just that you shouldn't use if x == True.

if x == True is silly because == is just a binary operator! It has a return value of either True or False, depending on whether its arguments are equal or not. And if condition will proceed if condition is true. So when you write if x == True Python is going to first evaluate x == True, which will become True if x was True and False otherwise, and then proceed if the result of that is true. But if you're expecting x to be either True or False, why not just use if x directly!

Likewise, x == False can usually be replaced by not x.

There are some circumstances where you might want to use x == True. This is because an if statement condition is "evaluated in Boolean context" to see if it is "truthy" rather than testing exactly against True. For example, non-empty strings, lists, and dictionaries are all considered truthy by an if statement, as well as non-zero numeric values, but none of those are equal to True. So if you want to test whether an arbitrary value is exactly the value True, not just whether it is truthy, when you would use if x == True. But I almost never see a use for that. It's so rare that if you do ever need to write that, it's worth adding a comment so future developers (including possibly yourself) don't just assume the == True is superfluous and remove it.


Using x is True instead is actually worse. You should never use is with basic built-in immutable types like Booleans (True, False), numbers, and strings. The reason is that for these types we care about values, not identity. == tests that values are the same for these types, while is always tests identities.

Testing identities rather than values is bad because an implementation could theoretically construct new Boolean values rather than go find existing ones, leading to you having two True values that have the same value, but they are stored in different places in memory and have different identities. In practice I'm pretty sure True and False are always reused by the Python interpreter so this won't happen, but that's really an implementation detail. This issue trips people up all the time with strings, because short strings and literal strings that appear directly in the program source are recycled by Python so 'foo' is 'foo' always returns True. But it's easy to construct the same string 2 different ways and have Python give them different identities. Observe the following:

>>> stars1 = ''.join('*' for _ in xrange(100))
>>> stars2 = '*' * 100
>>> stars1 is stars2
False
>>> stars1 == stars2
True

EDIT: So it turns out that Python's equality on Booleans is a little unexpected (at least to me):

>>> True is 1
False
>>> True == 1
True
>>> True == 2
False
>>> False is 0
False
>>> False == 0
True
>>> False == 0.0
True

The rationale for this, as explained in the notes when bools were introduced in Python 2.3.5, is that the old behaviour of using integers 1 and 0 to represent True and False was good, but we just wanted more descriptive names for numbers we intended to represent truth values.

One way to achieve that would have been to simply have True = 1 and False = 0 in the builtins; then 1 and True really would be indistinguishable (including by is). But that would also mean a function returning True would show 1 in the interactive interpreter, so what's been done instead is to create bool as a subtype of int. The only thing that's different about bool is str and repr; bool instances still have the same data as int instances, and still compare equality the same way, so True == 1.

So it's wrong to use x is True when x might have been set by some code that expects that "True is just another way to spell 1", because there are lots of ways to construct values that are equal to True but do not have the same identity as it:

>>> a = 1L
>>> b = 1L
>>> c = 1
>>> d = 1.0
>>> a == True, b == True, c == True, d == True
(True, True, True, True)
>>> a is b, a is c, a is d, c is d
(False, False, False, False)

And it's wrong to use x == True when x could be an arbitrary Python value and you only want to know whether it is the Boolean value True. The only certainty we have is that just using x is best when you just want to test "truthiness". Thankfully that is usually all that is required, at least in the code I write!

A more sure way would be x == True and type(x) is bool. But that's getting pretty verbose for a pretty obscure case. It also doesn't look very Pythonic by doing explicit type checking... but that really is what you're doing when you're trying to test precisely True rather than truthy; the duck typing way would be to accept truthy values and allow any user-defined class to declare itself to be truthy.

If you're dealing with this extremely precise notion of truth where you not only don't consider non-empty collections to be true but also don't consider 1 to be true, then just using x is True is probably okay, because presumably then you know that x didn't come from code that considers 1 to be true. I don't think there's any pure-python way to come up with another True that lives at a different memory address (although you could probably do it from C), so this shouldn't ever break despite being theoretically the "wrong" thing to do.

And I used to think Booleans were simple!

End Edit


In the case of None, however, the idiom is to use if x is None. In many circumstances you can use if not x, because None is a "falsey" value to an if statement. But it's best to only do this if you're wanting to treat all falsey values (zero-valued numeric types, empty collections, and None) the same way. If you are dealing with a value that is either some possible other value or None to indicate "no value" (such as when a function returns None on failure), then it's much better to use if x is None so that you don't accidentally assume the function failed when it just happened to return an empty list, or the number 0.

My arguments for using == rather than is for immutable value types would suggest that you should use if x == None rather than if x is None. However, in the case of None Python does explicitly guarantee that there is exactly one None in the entire universe, and normal idiomatic Python code uses is.


Regarding whether to return None or raise an exception, it depends on the context.

For something like your get_attr example I would expect it to raise an exception, because I'm going to be calling it like do_something_with(get_attr(file)). The normal expectation of the callers is that they'll get the attribute value, and having them get None and assume that was the attribute value is a much worse danger than forgetting to handle the exception when you can actually continue if the attribute can't be found. Plus, returning None to indicate failure means that None is not a valid value for the attribute. This can be a problem in some cases.

For an imaginary function like see_if_matching_file_exists, that we provide a pattern to and it checks several places to see if there's a match, it could return a match if it finds one or None if it doesn't. But alternatively it could return a list of matches; then no match is just the empty list (which is also "falsey"; this is one of those situations where I'd just use if x to see if I got anything back).

So when choosing between exceptions and None to indicate failure, you have to decide whether None is an expected non-failure value, and then look at the expectations of code calling the function. If the "normal" expectation is that there will be a valid value returned, and only occasionally will a caller be able to work fine whether or not a valid value is returned, then you should use exceptions to indicate failure. If it will be quite common for there to be no valid value, so callers will be expecting to handle both possibilities, then you can use None.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ben
  • 68,572
  • 20
  • 126
  • 174
  • Thank you for this answer. It cleared up a number of misconceptions that I have had for quite a while and clarified a few other points that were a little foggy. I had thought that True and False were like None in that python guaranteed that their ids would always be the same. Sadly this means that I have a lot of code to go look (grep) through... – Vorticity Feb 29 '12 at 07:20
  • 2
    @Vorticity: To be honest, Python quite possibly *does* guarantee that their ids are always the same, and even if it doesn't guarantee that I'm 99% sure that they will always be the same in practice. So I wouldn't necessarily rush to edit `x is True` out of all your code if you have better things to be doing (like writing new code :) ). But generally you only want to be using `is` tests with mutable objects (or `None`, which is the exception that proves the rule). – Ben Feb 29 '12 at 07:28
  • After thinking about this a bit more, I've got one question. How can you tell the difference between a variable that contains `int(13)` and one that contains `True`? Is it just that you normally don't care whether the variable is really `True` and just that it is truthy? I guess I'm asking this because I'm having to parse back and forth between an annoying file format that contains `"yes"` and `"no"` all over the place, but when in my code I would much rather be dealing with `True` and `False` so I've had to write code to go from one to the other with minimal fuss. – Vorticity Feb 29 '12 at 07:40
  • 1
    > The reason is that for these types we care about values, not identity. < I don't agree: `>>> False == 0 -> True >>> False is 0 -> False`. In some cases i want to be sure that a function return `False` not `0`, so i can't use `if a() == False` – warvariuc Feb 29 '12 at 07:43
  • 2
    @Vorticity Yeah, a straight `if x` will take the same path for `13` as for `True`. If you need to tell them apart, then you'll need to explicitly test against `True`. But be aware that e.g. `False or 3` returns `3`, not `True`! The contract of `and` and `or` is that they'll return a truthy or falsey value appropriately, not that they'll always give you `True` or `False`. – Ben Feb 29 '12 at 07:48
  • @warwaruk Huh. I actually didn't know that. I guess it makes some sense, since there's so many C programs where 1 and 0 are True and False. It is true though that if there happened to be another `False` at another memory address then testing `a() is False` would be wrong. The trouble is that the value equality is implemented such that two distinct values compare equal, not that identity is the right test to be making. – Ben Feb 29 '12 at 07:54
  • @Ben Well, that makes things fun. So, if I want to be sure that a value really is `True`, can I use `if type(foo) is type(True)` or does that run into the same problem as `if foo is True`? Note that I normally duck type rather than using `type()`. – Vorticity Feb 29 '12 at 07:56
  • 2
    I've read somewhere that True and False objects are unique, so i think using `x is True` should be ok... – warvariuc Feb 29 '12 at 08:09
  • 1
    > To sum up True and False in a sentence: they're alternative ways to spell the integer values 1 and 0 < http://docs.python.org/release/2.3.5/whatsnew/section-bool.html I think it wasn't intended for True/False to be used like `if x is True`, but nothing stops you to. – warvariuc Feb 29 '12 at 09:26
  • @warwaruk and Ben Thanks for all the help. I think this clears up my issues as well as they can be cleared up. – Vorticity Feb 29 '12 at 09:36
  • @warwaruk: True and False clearly *arent'* just alternative ways to spell 1 and 0 though. If they were implemented such you wouldn't be able to tell True and 1 apart, and if they were *conceptually* such you wouldn't want to. Clearly however True and 1 *are* different things (that's the rationale given for introducing booleans in that same page), and you want to be able to treat them differently. I think having them compare equal is a mistake. But that being the case, I guess you should use `is True` if you need to tell integers apart from booleans. I'll update my answer. – Ben Feb 29 '12 at 22:07
  • `isinstance(True, int) -> True` – warvariuc Mar 01 '12 at 07:22
  • 1
    @warwaruk Yes, that's because `bool` is a subclass of `int`, and therefore instances of `bool` are also instances of `int`. That doesn't mean that 1 and `True` are the same object (or `True is 1` would work). And people (you, at least) want to treat them as distinct. So they're not the same thing. As I've noted in the latest edit, `True` is also equal to 1.0 and 1L, but I certainly don't want to think of truth values the same way I think of floating point numbers. – Ben Mar 01 '12 at 07:32
  • It was just a note. Anyway i upvoted your answer - it is really good. See also: http://programmers.stackexchange.com/questions/12807/make-a-big-deal-out-of-true – warvariuc Mar 01 '12 at 07:35
  • @warwaruk Thanks for your comments too; my answer was a bit misleading before you pointed out that `True == 1`. – Ben Mar 01 '12 at 08:56
  • Note that the fact that `True == 1`/`False == 0` generally means testing `x == True` or `x == False` is the least useful case. If you really want to verify that you got an exact boolean value, `x is True` or `x is False` is the way to go. `x == True`/`x == False` is only for the incredibly rare case where receiving `1` or `0` (or `1.0` or `0.0` the like) should be treated as equivalent to the boolean values (but other non-zero values shouldn't be for some reason), but you don't want to accept other things as being truthy or falsy, which is a *really* limited use case. – ShadowRanger Jul 10 '19 at 22:35
  • @ShadowRanger I agree. 99% of the time you should just be using `if x` or `if not x`. If the condition you need to branch on cuts across a different axis than the standard truthy/falsey distinction then you're doing something very precise, so you need to (a) understand *exactly* how all this works (b) think very carefully about your code (c) document it carefully so that it isn't messed up by casual edits later. Frankly I'd suspect your code needs a refactor if you're getting values that could be mixed booleans or other types and you're *not* just treating them as truthy or falsey. – Ben Jul 11 '19 at 01:34
14

Use if foo or if not foo. There isn't any need for either == or is for that.

For checking against None, is None and is not None are recommended. This allows you to distinguish it from False (or things that evaluate to False, like "" and []).

Whether get_attr should return None would depend on the context. You might have an attribute where the value is None, and you wouldn't be able to do that. I would interpret None as meaning "unset", and a KeyError would mean the key does not exist in the file.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
strcat
  • 5,376
  • 1
  • 27
  • 31
  • Thanks for the answer and for the suggestion on "if foo". I guess I have always avoided it out of habit due to exactly what you point out about "is None". It never really crossed my mind that "if foo is True" is overly long. – Vorticity Feb 29 '12 at 06:39
9

If checking for truth:

if foo

For false:

if not foo

For none:

if foo is None

For non-none:

if foo is not None

For getattr() the correct behaviour is not to return None, but raise an AttributError error instead - unless your class is something like defaultdict.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kimvais
  • 38,306
  • 16
  • 108
  • 142
6

Concerning whether to raise an exception or return None: it depends on the use case. Either can be Pythonic.

Look at Python's dict class for example. x[y] hooks into dict.__getitem__, and it raises a KeyError if key is not present. But the dict.get method returns the second argument (which is defaulted to None) if key is not present. They are both useful.

The most important thing to consider is to document that behaviour in the docstring, and make sure that your get_attr() method does what it says it does.

To address your other questions, use these conventions:

if foo:
    # For testing truthiness

if not foo:
    # For testing falsiness

if foo is None:
    # Testing .. Noneliness ?

if foo is not None:
    # Check explicitly avoids common bugs caused by empty sequences being false

Functions that return True or False should probably have a name that makes this obvious to improve code readability:

def is_running_on_windows():
    return os.name == 'nt'

In Python 3 you can "type-hint" that:

>>> def is_running_on_windows() -> bool:
...     return os.name == 'nt'
... 
>>> is_running_on_windows.__annotations__
{'return': bool}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
wim
  • 338,267
  • 99
  • 616
  • 750
1

In the examples in PEP 8 (Style Guide for Python Code) document, I have seen that foo is None or foo is not None are being used instead of foo == None or foo != None.

Also using if boolean_value is recommended in this document instead of if boolean_value == True or if boolean_value is True. So I think if this is the official Python way. We Python guys should go on this way, too.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ismailarilik
  • 2,236
  • 2
  • 26
  • 37
1

One thing to ensure is that nothing can reassign your variable. If it is not a Boolean in the end, relying on truthiness will lead to bugs. The beauty of conditional programming in dynamically typed languages :).

The following prints "no".

x = False
if x:
    print 'yes'
else:
    print 'no'

Now let's change x.

x = 'False'

Now the statement prints "yes", because the string is truthy.

if x:
    print 'yes'
else:
    print 'no'

This statement, however, correctly outputs "no".

if x == True:
    print 'yes'
else:
    print 'no'
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kat
  • 577
  • 4
  • 7
1

You can directly check that a variable contains a value or not, like if var or not var.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nilesh
  • 20,521
  • 16
  • 92
  • 148
0

In the case of your fictional getattr function, if the requested attribute always should be available but isn't then throw an error. If the attribute is optional then return None.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

For True, not None:

if foo:

For false, None:

if not foo:
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sam
  • 18,509
  • 24
  • 83
  • 116