tags:

views:

123

answers:

4

At the end of python PEP8 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 recommandation when the boolean is True, but it sounds strange when checking for False

If I want to know if variable greeting is False why shouldn't I write:

    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 empty string ? Does this PEP8 recommandation 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 recommandation 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, does anyone know why if greeting is True: is described as worse that if greeting == True: ? Should we also understand that if greeting is False: is also worse that if greeting == False: ?

A: 

I usually name my boolean variables after the pattern IsName, so in you case 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.

Space_C0wb0y
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
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
@Walter: Good advice.
Space_C0wb0y
+2  A: 

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
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
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
Glenn Maynard: that's exactly the point, I quite often use 3 state booleans, where None means `undefined`.
kriss
Then you use `x is not None and not x`; this more commonly looks like `if x is None: ... elif not x: ...`.
Glenn Maynard
+2  A: 

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 false, 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
+1 Great answer!
mizipzor
No problems, @aaronasterling, I don't mind a bit of constructive criticism even if you think it may be nitpicking :-) Changed them to the correct names.
paxdiablo
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
A: 

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
`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
I can contrive of one: libraries with Pickle-like behavior, eg. pickling `False` is different than pickling `""`.
Glenn Maynard