Using foo is True
instead of foo == True
(or just foo
) if is most of the time not what you want.
I have seen foo is True
used for checking that the parameter foo
really was a boolean.
- It contradicts python's duck-typing philosophy (you should in general not check for types. A function acting differently with
True
than with other truthy values is counter-intuitive for a programmer who assumes duck-typing)
- Even if you want to check for types, it is better to do it explicity like :
def myFunction(foo):
if not isinstance(foo, bool):
raise ValueError("foo should be a boolean")
>>> myFunction(1)
Exception: ValueError "foo should be a boolean"
For several reasons:
- Bool is the only type where the
is
operator will be equivalent to isinstance(a, bool) and a
. The reason for that is the fact that True
and False
are singletons. In other words, this works because of a poorly known feature of python (especially when some tutorials teach you that True
and False
are just aliases for 1
and 0
). The is
operator is meant to check whether two objects are the same instance in memory. using it to check that something is a boolean is at best confusing.
- If you use isinstance and the programmer was not aware that your function did not accept truthy-values, or if they are using
numpy
and forgot to cast their numpy-boolean to a python-boolean, they will know what they did wrong, and will be able to debug.
Compare with
def myFunction(foo):
if foo is True:
doSomething()
else:
doSomethingElse()
In this case, myFunction(1)
not only does not raise an exception, but probably does the opposite of what it was expected to do. This makes for a hard to find bug in case someone was using a numpy boolean for example.
When should you use is True
then ?
EDIT: Please don’t. It’s explicitely advised against by PEP 8 as mentioned in comments on another answer.
EDIT: this is bad practice, starting from 3.9, python raises a warning when you try to use is
to compare with a literal. See @ JayDadhania's comment below. In conclusion is
should not be used to compare to literals, only to check the equality of memory address.
Just don't use it. If you need to check for type, use isinstance
.
Old paragraph:
Basically, use it only as a shorthand for isinstance(foo, bool) and foo
The only case I see is when you explicitely want to check if a value is true, and you will also check if the value is another truthy value later on. Examples include:
if foo is True:
doSomething()
elif foo is False:
doSomethingElse()
elif foo is 1: #EDIT: raises a warning, use == 1 instead
doYetSomethingElse()
else:
doSomethingElseEntirely()
True
andFalse
are singletons. Thebool
constructor will return eitherTrue
orFalse
by identity, so you cannot create a boolean value that won't compare equal to eitherTrue
orFalse
usingis
. – InvitingPyObject*
forTrue
and one forFalse
, same forNone
and integers below 257 – Toile