9

Can please someone explain how one may use 'is' in an 'if' condition. I am working with the fractions module, and I'm having some trouble:

>>> Fraction(0, 1) is 0
False
>>> float(Fraction(0, 1))
0.0
>>> float(Fraction(0,1)) is 0.0
False

The only thing I found to work is:

>>> F = Fraction(a,b)
>>> if F >= 0:
...     if F(0, 1) <= 0:
...                      ...

Is there a way to use 'is' here? Thanks.

milcak
  • 260
  • 1
  • 3
  • 13
  • 1
    A relevant answer comparing `is` and `==` for fractions is [here](http://stackoverflow.com/questions/2576826/pythons-preferred-comparison-operators/2577494#2577494). – Scott Griffiths Jun 04 '11 at 10:49

5 Answers5

6

From the documentation:

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.

What you want here is ==, to test whether two objects are equal or equivalent by comparing the values and not the identities.

A trivial example (in CPython that may differ in other implementations):

>>> 1 + 2 == 3.0
True
>>> 1 + 2 is 3.0
False
>>> 1 + 2 is 3
True
>>> id(1 + 2)
4298185512
>>> id(3.0)
4298194656
>>> id(3)
4298185512
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
  • 2
    Note that `1+2 is 3` happens to be `True` because of a coincidence (small integers are preallocated for performance reasons). – 6502 Jun 04 '11 at 09:30
6

The is operator in python is used to check if two variables are pointing to the very same object and is not meant to be used to check about numeric equality. You should use == for that instead.

For example consider that

(1000 + 1000) is (1000 + 1000)

returns False.

6502
  • 112,025
  • 15
  • 165
  • 265
5

is checks for object identity. It returns true if two names refer to the same object. One typical usecase is to check if a name refers to None:

if foo is None:
    # do stuff
Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • but why isn't 0.0 is 0.0? doesn't python save both under one object? – milcak Jun 04 '11 at 08:41
  • For Fractions, no it doesn't. It does for a few types that are optimised for performance (such as integers and binary floating point), but that's an implementation detail that shouldn't be relied on in your own code. – ncoghlan Jun 04 '11 at 08:43
  • Nastily, it does for small integers. But that's an implementation detail. Generally, interning every possible value that crops up isn't worth it. –  Jun 04 '11 at 08:44
  • 1
    Like Space_C0wb0y said, it does not. 0.0 and 0.0 points to two different places in memory. "Is" compares the identity of the references and "==" compares the actual value of the two references. – rzetterberg Jun 04 '11 at 08:45
  • @milcak, generally - no. Python does intern'ing for some basic types like ints and strings, and only for small/short values, but this is implementation detail and you should not rely on it. If you want to test equality, you should use `==`. `is` is for checking that this is _same object_ (located in same place in memory), rather than _same meaning of two objects_. – Daniel Kluev Jun 04 '11 at 08:47
  • Just a bit off topic comment! For `float` numbers, do not use `float1 == float2` for comparison! Use `abs(float1 - float2) < 1e-8` (or whatever small (but not too small) value, whish fits to your purpose) instead! – TrueY Feb 16 '22 at 08:35
3

a is b is equivalent to id(a) == id(b)

saeedgnu
  • 4,110
  • 2
  • 31
  • 48
0

Quote from http://docs.python.org/library/operator.html:

operator.is_(a, b) Return a is b. Tests object identity.

rzetterberg
  • 10,146
  • 4
  • 44
  • 54