7

I was (maybe wrongfully) thinking that is operator is doing id() comparison.

>>> x = 10
>>> y = 10
>>> id(x)
1815480092
>>> id(y)
1815480092
>>> x is y
True

However, with val is not None, it seems like that it's not that simple.

>>> id(not None)
2001680
>>> id(None)
2053536
>>> val = 10
>>> id(val)
1815480092
>>> val is not None
True

Then, what does 'is' operator do? Is it just object id comparison just I conjectured? If so, val is not None is interpreted in Python as not (val is None)?

prosseek
  • 182,215
  • 215
  • 566
  • 871
  • Yes, `val is not None` and `not (val is None)` are [equivalent](http://stackoverflow.com/questions/12941287/does-not-e-in-c-differ-from-e-not-in-c-in-python). But the first one is more readable IMO. – Ashwini Chaudhary Aug 16 '13 at 14:32

3 Answers3

11

You missed that is not is an operator too.

Without is, the regular not operator returns a boolean:

>>> not None
True

not None is thus the inverse boolean 'value' of None. In a boolean context None is false:

>>> bool(None)
False

so not None is boolean True.

Both None and True are objects too, and both have a memory address (the value id() returns for the CPython implementation of Python):

>>> id(True)
4440103488
>>> id(not None)
4440103488
>>> id(None)
4440184448

is tests if two references are pointing to the same object; if something is the same object, it'll have the same id() as well. is returns a boolean value, True or False.

is not is the inverse of the is operator. It is the equivalent of not (op1 is op2), in one operator. It should not be read as op1 is (not op2) here:

>>> 1 is not None     # is 1 a different object from None?
True
>>> 1 is (not None)   # is 1 the same object as True?
False
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • It is important to mention that `is not` is a single operator. `True is (not 1) -> False`, `True is not 1 -> True`. So what `not None` returns is irrelevant. – Pavel Anossov Aug 16 '13 at 14:35
  • @PavelAnossov The return value of `not None` is relevant because OP used `(not None)` in one example. –  Aug 16 '13 at 14:37
  • @delnan: exactly, because apparently the OP missed that `is not` is a single operator. It looks like `op1 is (not None)` was expected. Which would be `False`, not `True`. – Martijn Pieters Aug 16 '13 at 14:40
  • "The operators `is` and `is not` test for object identity: `x is y` is true if and only if x and y are the same object. `x is not y` yields the inverse truth value." http://docs.python.org/release/2.7/reference/expressions.html#notin – KurzedMetal Aug 16 '13 at 14:44
3

As a complement to Martijn Pieters answer, None, True and False are singletons. There is only one instance of each of these values so it is safe to use is to test them..

>>> id(True)
8851952
>>> id(False)
8851920
>>> id(None)
8559264
>>> id(not None)
8851952
>>> id(1 == 0)
8851920
>>> id(1 == 1)
8851952
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
  • For `None` I agree, for `False` and `True` it might be an implementation detail. Nevertheless, testing `if xxx is True:` sounds silly to me; a mere `if xxx:` should be better. – glglgl Aug 16 '13 at 15:09
  • @glglgl I agree. I just introduced `True` and `False` in the discussion as the original question mentioned `is (not None)`. That is, using the `is` operator to compare with the boolean value `(not None)` -- which is not the same as using the `is not` operator as explained in other comments. – Sylvain Leroux Aug 16 '13 at 15:15
  • @glglgl you can easily come up with a pathological case for `xxx is True`: returned error codes, in the manner of linux processes. If a function succeeds, it returns True, if it fails, it returns an error code, which may be greater than 0, and hence would also evaluate to true. Admittedly, there's far better ways of doing this, but we're being pathological here. (Admittedly the above makes more sense to a reader than the needed `if !result:` with linux-esque zero-for-success.) – RoadieRich Aug 16 '13 at 15:21
0

Python tries to emulate the English language syntax to make it more human readable, but in this instance the operator precedence is a little confusing.

>>> val is not None
True

In English, we are asking if val does not have a value that is represented by the same object as None. In your above example val=10, so the answer is (correctly) True.

However, from a logical, syntactical viewpoint you have broken down the statement word-for-word and assumed it to be:

>>> val is (not None)
False

which, when enclosed in appropriate patentheses, returns your expected result (False).

As @Martijn Pieters points out, is not is an operator in its own right, and it the only operator at work here.

If you wanted to write it as a non ambiguous statement using only operators that contain no spaces, you could write:

>>> not (val is None)
True

But that is not how you would 'say' the intended statement in English, or possibly even write it in pseudo-code.

Lee Netherton
  • 21,347
  • 12
  • 68
  • 102