22

At the end of Python PEP 8 I'm reading:

  • Don't compare Boolean values to True or False using ==

     Yes:   if greeting:
     No:    if greeting == True:
     Worse: if greeting is True:
    

I have no problem with that recommendation when the Boolean is True, but it sounds strange when checking for False.

If I want to know if a variable greeting is False, why shouldn't I write the following?

    if greeting == False:

If I write if not greeting: it will have a very different meaning that the above statement. What if greeting is None? What if it is an empty string? Does this PEP 8 recommendation means that variables storing Boolean values should only contains True or False and that None should be avoided for these variables?

To my eyes it looks like a recommendation coming from other languages with static typing and that does not fit well with Python, at least for comparing to False.

And by the way, why is if greeting is True: described as worse than if greeting == True:? Should we also understand that if greeting is False: is also worse that if greeting == False:?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kriss
  • 23,497
  • 17
  • 97
  • 116
  • 1
    ... Why would it sometimes be `None`, sometimes be a bool, and sometimes be a str? That's just asking for all sorts of trouble. – Ignacio Vazquez-Abrams Oct 29 '10 at 08:50
  • 2
    The str case is probably irrelevant. But the None case can occur if you have a policy of initializing all returned variables before computing their values. If some exception occured before computing the boolean is is still None and you may want to know it wasn't computed. – kriss Oct 29 '10 at 09:12
  • 2
    But that's what `is None` is for. – Ignacio Vazquez-Abrams Oct 29 '10 at 09:14
  • 1
    You mean instead of `if greeting == False:` I should prefer `if greeting is not None and not greeting:` Or using cascading ifs beginning by `if greeting is None` ? – kriss Oct 29 '10 at 09:24
  • 2
    First you use `is None`/`is not None` to verify success. Then you go from there. – Ignacio Vazquez-Abrams Oct 29 '10 at 09:26
  • You've accepted an answer because it tells you what you want to hear--even though it gives no justification or examples--over one that explains in detail why you shouldn't do this. You've dismissed everyone who's told you the right way to do it. Apparently, you just wanted "permission" to do things the wrong way. – Glenn Maynard Oct 29 '10 at 22:09
  • http://en.wikipedia.org/wiki/Confirmation_bias – Glenn Maynard Oct 29 '10 at 23:23
  • @Glenn Maynard: not really, I choosed that answer by default because I really got no answer and wanted to close subject (other answers where kind of inverted, more or less "it should be good because PEP8 say it, ignore the (indeed rare) cases where it is not". Is it seriously an answer ? For all it is worth, the most serious answer I got is probably the one from Ignacio Vasquez-Abrams (check None as a separate value), but I can't choose it as it is in a comment, not an answer. Other option would have been to completely remove the question, but I do not feel it was correct behavior either. – kriss Oct 30 '10 at 06:56
  • You asked why not to write `x == False`, and I gave you a detailed answer which thoroughly explains why that's a bad idea, and doesn't refer to PEP8 at all. – Glenn Maynard Oct 30 '10 at 08:53
  • 2
    Follow your idea to the end. If what you say was the simple truth and there was no exceptions, there would be no need for a False distinguished value to exist at all. A boolean value True/None would be enough for all purposes. I just can't agree with that. But I did not downvoted your answer either. As far as I can understand it, you're just stating that in most practical cases distinguishing between False and other false value is not necessary. I *do* agree with that, but it's not the end of the story. – kriss Oct 30 '10 at 10:43
  • **Don't compare boolean values to True or False using ==** If the value can be None or empty string, this rule doesn't apply. It must be strictly `True` or `False` – John La Rooy Nov 24 '15 at 03:19
  • @John La Roy: as I read it the boolean value is the litteral True or False on the left of expressions. On the other side of comparison it's a variable, not a value, and many possible content of variables are equivalent to False in expressions. – kriss Nov 24 '15 at 14:36
  • I read it as "Boolean value" is referring to `greeting`, "True or False" is referring to the constant (on the RHS in this case). Perhaps it could be expressed more clearly in PEP8 though. – John La Rooy Nov 24 '15 at 18:27

6 Answers6

19

I believe you're reading it wrong. Try not to think of greeting as a noun so much as a verb ("I am greeting" instead of "This is a greeting").

You can see the clue in the preamble to PEP8:

One of Guido's key insights is that code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code.

To that end, code should resemble the written or spoken word as much as possible. You don't say "If I am annoying you is true, let me know" in real life, you just say "If I am annoying you, let me know".

That's one reason why you tend to see boolean variables like isOpen and hasBeenProcessed a lot since they aid in readability of the code.

You should never do something like:

if (isOpen == True)

or:

if (customerDead == False)

simply because you already have a boolean value in the variable name. All the equality is giving you is another boolean value and, invoking reduction ad absurdum, where would you stop?

if (isComplete == True) ...
if ((isComplete == True) == True) ...
if (((isComplete == True) == True) == True) ...
if ((((isComplete == True) == True) == True) == True)...
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 6
    This cosmetic argument is valid, but I think it misses the question somewhat. The OP is asking about the *functional* difference between saying `not x` and `x is False`. He does seem to understand the difference, and I think he wants to know why the *behavior* of the former is recommended over the latter. – Glenn Maynard Oct 29 '10 at 10:44
  • Great answer! This reminds me of "Buffalo buffalo buffalo..." – stantonk Dec 11 '12 at 16:49
  • Shouldn't it be "If I am annoying you is `true`, let me know"? – Framester Mar 01 '13 at 18:49
  • Quite right, @Framester, I've changed it based on your suggestion. Thanks for that. – paxdiablo Mar 01 '13 at 22:23
  • But, if I want to check if `isOpen` is `False`? How am I supposed to write the conditional? – gon1332 Jul 31 '14 at 12:44
  • @gon1332: `if not isOpen: ...`. – paxdiablo Jul 31 '14 at 14:24
7

The simplest reason to not compare truth via == or != comparisons seems to be this:

0 is False # Result: False
0 == False # Result: True; 0 evaluates comparatively to False

1 is True  # Result: False
1 == True  # Result: True; 1 evaluates comparatively to True

is checks whether the value passed is exactly True/False, not whether it evaluates to True or False.

This behavior allows this:

if var is False:
   # False (bool) case
elif var is None:
   # None case
elif var == 0:
   # integer 0 case

whereas

if var == False:
    # catches False & 0 case; but not None case, empty string case, etc.

which seems counter-intuitive -- which is why I expect PEP 8 says "don't do it".

As said here use is for identity, but use == for equality.

You'd only want to use if var is True when you need the bool value True, but want to reject 1, 'some string', etc.

Such cases are probably not obvious to most readers; I suspect PEP 8 claims it's "Worse" for being potentially misleading. From time to time it may be a necessary evil; but... if you find yourself needing is True, it may be indicating a design issue. In any case, you should probably comment "why" you need exactly True or False if you do ever use is.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ryan de Kleer
  • 1,246
  • 14
  • 24
  • 1
    interesting point, even if it's not obvious if it goes in the same direction as PEP8 (PEP8 is pointing `is True` as worse as `== True`) – kriss May 01 '15 at 17:32
5

This is part of duck typing. In Python, you usually don't want to restrict what you accept to a specific class, but to an object that exposes the proper API. For example, I can do this:

class MyProperty(object):
    """
    A file-backed boolean property.
    """
    def __init__(self, filename):
        self.value = open(filename).read()
    def __nonzero__(self):
        return self.value != "0"
    def save_to_disk(self):
        # ... and so on
        pass

def func(enabled):
    if not enabled:
        return
    # ...

enable_feature = MyProperty("enable_feature")
func(enable_feature)

Saying if enabled == False would cause this to not work.

False is a false value, but it's not the only false value. Avoid comparing to True and False for the same reason you avoid using isinstance.

Glenn Maynard
  • 55,829
  • 10
  • 121
  • 131
  • I understand what you say, but writing `g == False` looks to me exactly like writing `len(g) == 0`, it seems like the proper way to do things in some context. When writing `len(g) == 0`, my goal is usually to rule out the case where g is None. Should I rely on duck typing for this case and expect some other error that detect g is None and hence has no length ? I see no fundamental difference between both forms here. – kriss Oct 29 '10 at 11:18
  • Why would you want to rule out None for truth testing? It's valid (if unidiomatic) to pass None to a function in lieu of False, unless None is specifically defined to mean something else in that context. – Glenn Maynard Oct 29 '10 at 11:42
  • Glenn Maynard: that's exactly the point, I quite often use 3 state booleans, where None means `undefined`. – kriss Oct 29 '10 at 17:01
  • Then you use `x is not None and not x`; this more commonly looks like `if x is None: ... elif not x: ...`. – Glenn Maynard Oct 29 '10 at 22:05
  • @kriss it may currently be the case that `len(g) == 0` for all things that are not None and falsey, but as far as I know that is not guaranteed. `len(None)` raises `TypeError: object of type 'NoneType' has no len()` - so instead of explicitly checking for `None` you're implicitly raising an error that either you or your caller need to handle. That seems less elegant to me than explicitly checking for `None` in your test, if you want to handle that specially. – pcurry May 24 '15 at 22:50
  • @pcurry: https://docs.python.org/3/reference/datamodel.html#object.__len__ the `len(g) == 0`idiom works for all objects having the Sized trait (ie: containers). Indeed we have to check for None if we do that. Buf if we write `if g: ...` instead it works for both None and length checking : http://stackoverflow.com/questions/7771318/the-most-pythonic-way-of-checking-if-a-value-in-a-dictionary-is-defined-has-zero – kriss May 25 '15 at 13:59
4

The way I understand it the PEP's recommendation implies that, if you know can be reasonably sure of the type of foo (which is usually the case), then testing for the explicit false value is redundant and reduces readability. For example, in foo = [i for i in range(10) if i == x], you can be fairly sure that the only false value foo can have is [] (assuming no exceptions are raised). In this case it is redundant to use foo == [] and not foo is better.

On the other hand the semantic value of foo == [] or foo == False is sometimes more valuable and should then be used (IMHO) in stead of not foo. It depends on what, specifically, you are trying to communicate. In fact not foo means "foo has a false value?", whereas foo == False means "foo has the same value as False?".

The PEP states that everything it contains are guidelines. There are exceptions to rules and this one is no different.

Walter
  • 7,809
  • 1
  • 30
  • 30
  • 2
    `foo == False` should almost *never* be used; I can't even contrive of a case where it's the correct thing to do. – Glenn Maynard Oct 29 '10 at 21:50
  • 3
    I can contrive of one: libraries with Pickle-like behavior, eg. pickling `False` is different than pickling `""`. – Glenn Maynard Oct 29 '10 at 21:56
  • 1
    I think if foo == False reads more like English than if not foo. – tponthieux Jul 17 '12 at 22:00
  • 4
    i've certainly never heard an english speaker say "if going to the store today equals equals false" – Eevee May 10 '14 at 23:27
  • @GlennMaynard: But `0 == False`, so that check really needs to be `foo is False`. (PEP 8's recommendations regarding `== True` and `is True` have always seemed backward to me; `is` is occasionally necessary, while `==` is almost always wrong in any case where the input type isn't already known.) – user2357112 Apr 12 '18 at 16:41
  • Recommending _foo == False_ is one of the signs of lousy programming style and unprofessionalism – volcano Jul 06 '18 at 09:10
1

I’m not sure other comments answered your question. You say:

If I write if not greeting: it will have a very different meaning that the above statement. What if greeting is None? What if it is empty string?

Indeed, not greeting and greeting == False have different meaning. But the PEP 8 is not saying the opposite and it's not saying to not use greeting == False. It says:

Don't compare boolean values to True or False using ==

Neither None nor the empty string is a Boolean value. So use greeting == False if appropriate and greeting can be non-Boolean.


Someone commented below your questions:

... Why would it sometimes be None, sometimes be a bool, and sometimes be a str? That's just asking for all sorts of trouble.

That’s not. Here is a use case: You have a database of patients with a field saying whether the patient died from suicide or not. Let’s say we have class Patient with attribute suicide. suicide would have three possible values:

  • True meaning "yes, we know he committed suicide"
  • False meaning "no, we know he died from something else"
  • None meaning "we don't know actually".

Then, if you want to study patients not dying from suicide, you would do something like:

# load database
...

# Filter patients
database = [patient for patient in database if patient.suicide == False]  # if greeting == False:

# Study database
...

QED. This is a typical case in data science. Value False means you know something is false whereas value None means you don't know anything.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alexandre Huat
  • 806
  • 10
  • 16
0

I usually name my Boolean variables after the pattern IsName, so in your case it is IsGreeting. This makes the check read if IsGreeting/if not IsGreeting, which is very intuitive.

The ambiguities you are describing with if not are the result of using non-Boolean types in Boolean comparisons. This should usually be avoided, as it is very confusing.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • I basically do like you, but I explained in comment below the question why I belive None could happen. In a perfect universe no problem. But in real world, writing statement like `if not IsGreeting:` seems to be calling for troubles because shit happens. – kriss Oct 29 '10 at 09:18
  • 4
    Since this is a PEP8-related question... PEP8 recommends that variable name identifiers start with a lower case letter and use underscores in stead of camel case. Camel case (starting with a capital) is recommended for class names. – Walter Oct 29 '10 at 09:48