8

From this link I learnt that

The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object

But when I tried to give some example for my session and I found out that it behaves differently with assignment and tuple unpacking.

Here is the snippet:

>>> a,b = 300,300
>>> a is b
True
>>> c = 300
>>> d = 300
>>> c is d
False
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
James Sapam
  • 16,036
  • 12
  • 50
  • 73
  • 4
    It's not defined how `is` behaves for integers. Any knowledge you gain about how one implementation behaves today will be fragile. – Paul Hankin Dec 22 '13 at 12:55
  • 1
    @Anonymous: "Implementation-defined" is more accurate than "not defined", but the statement about fragility still holds – Eric Dec 22 '13 at 12:58
  • possible duplicate of [Weird Integer Cache inside Python 2.6](http://stackoverflow.com/questions/15171695/weird-integer-cache-inside-python-2-6). Not exactly the same question but the accepted answer (disclaimer: mine) shows what happens in the case of tuples which I believe it's enough to answer your question: it's the so-called peephole optimizer that avoid duplicating constants. – Bakuriu Dec 22 '13 at 14:13
  • Thank you @Bakuriu, found some interesting explanation. – James Sapam Dec 22 '13 at 14:22

2 Answers2

7

Because int is immutable, Python may or may not use exists object, if you save the following code in to a script file, and run it, it will output two True.

a, b = 300, 300
print a is b

c = 300
d = 300
print c is d

When Python compile the code, it may reuse all the constants. Becasue you input your code in a python session, the codes are compiled line by line, Python can't reuse all the constants as one object.

The document only says that there will be only one instance for -5 to 256, but doesn't define the behavior of others. For immutable types, is and is not is not important, because you can't modify them.

HYRY
  • 94,853
  • 25
  • 187
  • 187
  • You can simulate this on the interpreter prompt by putting all your code in a single function and then running it (as opposed to running them one at a time). – Noufal Ibrahim Dec 22 '13 at 12:57
2
 import dis

 def testMethod1():
     a, b = 300, 300

 print dis.dis(testMethod1)

Prints:

4 0 LOAD_CONST 2 ((300, 300))
3 UNPACK_SEQUENCE 2
6 STORE_FAST 0 (a)
9 STORE_FAST 1 (b)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE None

 def testMethod2():
     a = 300
     b = 300

Prints:

7 0 LOAD_CONST 1 (300)
3 STORE_FAST 0 (a)
8 6 LOAD_CONST 1 (300)
9 STORE_FAST 1 (b)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE None

So, it looks essentially the same, but with LOAD_CONST in one step in the first method and two steps in the second method....

EDIT
After some testing, I discovered that both methods return False eventually; however, on one run only, ie not putting the methods in a loop, they seem to always return True. Sometimes it uses a single reference, and sometimes it does not.

The documentation only states that -5 to 256 will return the same reference; hence, you simply just shouldn't be using is for comparison (in this case) as the number's current id has no guarantee on it.

NB: You never want to use is for comparison of values, as that's not what it's for, it's to compare identities. My point was that is's return value is not always going to be True when you're outside of the defined range.

Steve P.
  • 14,489
  • 8
  • 42
  • 72
  • Hi Steve P, I tested in osx, python 2.7.2 – James Sapam Dec 22 '13 at 12:49
  • It is up to the Python implementation. Loading in two steps gives more time to free low level cache memory. The cache [-5, 256] happens in Python code, but imutable objects (like int) can be reused. You can't trust these caches. – iurisilvio Dec 22 '13 at 12:55
  • 1
    Apropos your last paragraph, `is` is not to be used for "comparison". `is` should be used for "identity". Comparing a and b is like saying "is a equal to b". Testing identity is like saying "are a and b the same thing" – Noufal Ibrahim Dec 22 '13 at 12:59
  • @NoufalIbrahim I understand what `is` does. What I'm saying is that you don't want to be using `is` for the sake of comparison (in this case). – Steve P. Dec 22 '13 at 13:01