views:

994

answers:

6

I've always thought of the if not x is None version to be more clear, but Google's style guide implies (based on this excerpt) that they use if x is not None. Is there any minor performance difference (I'm assuming not), and is there any case where one really doesn't fit (making the other a clear winner for my convention)?*

*I'm referring to any singleton, rather than just None.

...to compare singletons like None. Use is or is not.

+8  A: 

Both Google and Python's style guide is the best practice:

if x is not None:
    # Do something about x

Using not x can cause unwanted results. See below:

>>> x = 1
>>> not x
False
>>> x = [1]
>>> not x
False
>>> x = 0
>>> not x
True
>>> x = [0]         # You don't want to fall in this one.
>>> not x
False

You may be interested to see what literals are evaluated to True or False in Python:

Edit for comment below:

I just did some more testing. not x is None doesn't negate x first and then compared to None. In fact, it seems the is operator has a higher precedence when used that way:

>>> x
[0]
>>> not x is None
True
>>> not (x is None)
True
>>> (not x) is None
False

Therefore, not x is None is just, in my honest opinion, best avoided.

More edit:

I just did more testing and can confirm that bukzor's comment is correct. (At least, I wasn't able to prove it otherwise.)

This means if x is not None has the exact result as if not x is None. I stand corrected. Thanks bukzor.

However, my answer still stands: Use the conventional if x is not None. :]

Xavier Ho
I don't see how that's strange or unexpected. `False` values in Python are `False`, `None`, 0, an empty list/dictionary/tuple/set/string maybe some other empty stuff. [0] is a list that contains 1 element and definitely should be expected to be True (and hence it's negation is False)
Davy8
@orokusaki, By the way, performance has no impact one way or the other either way.
Xavier Ho
@Davy8: You are indeed correct. However, it can be unexpected for people new to Python. Besides, would you ever use `not x is None`? Anyway, I fixed the wording, thanks. `:]`
Xavier Ho
@Xavier Ho. Your answer is misleading. The 'not x' is not part of the problem here. Note that 'not 1 is True' evaluates to True and '(not 1) is True' evaluates to False. The 'x is not y' is exactly identical, semantically, to 'not x is y'.
bukzor
I would probably use `not x == None` out of habit from other languages, but I do like `x is not None` better.
Davy8
@bukzor: Thanks. I added your insight into the post.
Xavier Ho
+1  A: 

if not x is None is more similar to other programming languages, but if x is not None definitely sounds more clear (and is more grammatically correct in English) to me.

That said it seems like it's more of a preference thing to me.

Davy8
+11  A: 

Code should be written to be understandable to the programmer first, and the compiler or interpreter second. The "is not" construct resembles English more closely than "not is".

Mark Ransom
In addition, `is not` is defined as a single operator in Python. [1] Compare that with `not...is`, which is logically negating the `is` operation, thus requiring more than one operation. [1]: http://docs.python.org/py3k/reference/expressions.html#grammar-token-comp_operator
Dustin
@Dustin They compile to the same bytecode. See my answer for the disassembly output.
Daniel Stutzbach
+28  A: 

There's no performance difference, as they compile to the same bytecode:

Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39)
>>> import dis
>>> def f(x):
...    return x is not None
...
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> def g(x):
...   return not x is None
...
>>> dis.dis(g)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

Stylistically, I try to avoid not x is y. Although the compiler will always treat it as not (x is y), a human reader might misunderstand the construct as (not x) is y. If I write x is not y then there is no ambiguity.

Daniel Stutzbach
+1 for disassembly output. I always forget the `dis` module exists... And for the record, the same output is seen with Python 3.1.2 here.
Dustin
Nicely put. Your answer is way convincing than mine. +1.
Xavier Ho
Unless the same human reader thought it was `x is (not y)`. But I tend to agree with you for your other reasoning.
Etaoin
@Daniel Thanks for this. This question has been an eye opener for me.
orokusaki
+2  A: 

The is not operator is preferred over negating the result of is for stylistic reasons. "if x is not None:" reads just like English, but "if not x is None:" requires understanding of the operator precedence and does not read like english.

If there is a performance difference my money is on is not, but this almost certainly isn't the motivation for the decision to prefer that technique. It would obviously be implementation-dependent. Since is isn't overridable, it should be easy to optimise out any distinction anyhow.

Mike Graham
+2  A: 

The answer is simpler than people are making it.

There's no technical advantage either way, and "x is not y" is what everybody else uses, which makes it the clear winner. It doesn't matter that it "looks more like English" or not; everyone uses it, which means every user of Python--even Chinese users, whose language Python looks nothing like--will understand it at a glance, where the slightly less common syntax will take a couple extra brain cycles to parse.

Don't be different just for the sake of being different, at least in this field.

Glenn Maynard