4

Possible Duplicate:
Python “is” operator behaves unexpectedly with integers

Usually I use the type(x) == type(y) to compare if the types are the same. And then usex==y to compare if the numerical values are equal.

However, someone proposed that one may just use z1 is z2 to compare if the z1 and z2 are containing the same type of numbers with exactly the same value. In many cases, it will be successful (especially for the positive ints).

However, sometimes the same number (mostly the negative ints) can have several different instances. Is this an expected behavior of python?

For example:

>>> for x in range(-20,125):
    z1=x
    z2=int(float(x))
    if z1 is not z2:
        print "z1({z1}; type = {typez1}; id={idz1}) is not z2({z2}; type = {typez2}; id={idz2})".format(z1=z1,typez1=type(z1),idz1=id(z1),z2=z2,typez2=type(z2),idz2=id(z2))


z1(-20; type = <type 'int'>; id=33869592) is not z2(-20; type = <type 'int'>; id=33870384)
z1(-19; type = <type 'int'>; id=33870480) is not z2(-19; type = <type 'int'>; id=33870408)
z1(-18; type = <type 'int'>; id=32981032) is not z2(-18; type = <type 'int'>; id=33870384)
z1(-17; type = <type 'int'>; id=33871368) is not z2(-17; type = <type 'int'>; id=33870408)
z1(-16; type = <type 'int'>; id=33869712) is not z2(-16; type = <type 'int'>; id=33870384)
z1(-15; type = <type 'int'>; id=33869736) is not z2(-15; type = <type 'int'>; id=33870408)
z1(-14; type = <type 'int'>; id=33869856) is not z2(-14; type = <type 'int'>; id=33870384)
z1(-13; type = <type 'int'>; id=33869280) is not z2(-13; type = <type 'int'>; id=33870408)
z1(-12; type = <type 'int'>; id=33868464) is not z2(-12; type = <type 'int'>; id=33870384)
z1(-11; type = <type 'int'>; id=33868488) is not z2(-11; type = <type 'int'>; id=33870408)
z1(-10; type = <type 'int'>; id=33869616) is not z2(-10; type = <type 'int'>; id=33870384)
z1(-9; type = <type 'int'>; id=33871344) is not z2(-9; type = <type 'int'>; id=33870408)
z1(-8; type = <type 'int'>; id=33869064) is not z2(-8; type = <type 'int'>; id=33870384)
z1(-7; type = <type 'int'>; id=33870336) is not z2(-7; type = <type 'int'>; id=33870408)
z1(-6; type = <type 'int'>; id=33870360) is not z2(-6; type = <type 'int'>; id=33870384)
>>> x
124
>>> print x
124
>>> import sys
>>> print sys.version
2.7.2+ (default, Oct  4 2011, 20:06:09) 
[GCC 4.6.1]
Community
  • 1
  • 1
Wang
  • 7,250
  • 4
  • 35
  • 66
  • 3
    http://stackoverflow.com/questions/306313/python-is-operator-behaves-unexpectedly-with-integers has an answer for you as well – Andrew Cox Jul 23 '12 at 18:43
  • 6
    Who proposed that? They should be smacked. –  Jul 23 '12 at 18:43
  • 1
    This is true (in CPython) for a small subset of integers. This behavior should NOT be relied upon as it is not guaranteed to be identical across python implementations. – Joel Cornett Jul 23 '12 at 18:56

4 Answers4

6

Yes. Only a few numbers close to 0 (more positive than negative, as you've discovered) are interned by the compiler. Since an expression may result in a number outside this range, is should never be used to check for equality.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Do you know the range of those numbers? (I believe it's -5 to 256 inclusive). It also might be important to note that interning behavior is not guaranteed and might not be the same across all python implementations. – Joel Cornett Jul 23 '12 at 18:53
  • 1
    @JoelCornett it really doesn't matter which ones they are, since as you mentioned, it's implementation dependent. – Colin Dunklau Jul 23 '12 at 18:54
  • The result of the expression is irrelevant. `is` should _never_ be used to check for equality (EVER), since the interning of ints is implementation-dependent. – Colin Dunklau Jul 23 '12 at 18:55
  • Thanks! Actually it surprised me that the `is` can actually work for some numbers. So it is good to know there are some interned objects. – Wang Jul 23 '12 at 18:56
  • @Wang strike that from your memory, as you should never use it, even if it "works". – Colin Dunklau Jul 23 '12 at 18:57
  • And it doesn't always work for the interned numbers either. I can't remember which functions, but some functions return new instances instead of the interned numbers. So never, ever, use "is" to check for numerical equality. – casevh Jul 24 '12 at 04:38
1

According to the Python 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.

So even if x and y are the same type and are equal, they might not satisfy the is relation.

Kevin
  • 74,910
  • 12
  • 133
  • 166
0

The only proper use of is is to compare equality of identity of objects. To compare equality of value, use ==.

ncmathsadist
  • 4,684
  • 3
  • 29
  • 45
0

The 'is' keyword compares the identity of two objects(basically the memory location at which they are stored), NOT the value. It should not be used to check for equality.

The 'is' keyword succeeded a few times in your case due to specifics of the implementation of your interpreter - some numbers are stored by your compiler for easy access. You should not expect or rely on this behavior.

Lanaru
  • 9,421
  • 7
  • 38
  • 64