4

In simple terms, why this code returns False and not true:

a = 10
print(id(a) is id(a)) # why false?

id() returns integer, and same integer vars point to the same integer object. Why it returns false then? What is the difference with:

a = 10
b = 10
print(a is b) # it returns True

Thanks for explanation.

Cleptus
  • 3,446
  • 4
  • 28
  • 34
Paweł Bąkiewicz
  • 207
  • 1
  • 2
  • 8
  • “and same integer vars point to the same integer object” — what makes you think that? Think about it: how would this be implemented efficiently in the Python interpreter? It would require potentially caching billions of objects … at the cost of gigabytes of memory. – Konrad Rudolph Nov 12 '19 at 10:04

2 Answers2

2

Because, while it is true that

a is a

id(a) is a large integer and does not compare by is

>>> a = 10
>>> print(id(a) is id(a))
False
>>> print(id(a),id(a))
(44337068, 44337068)
>>>

Check https://docs.python.org/2/c-api/int.html#c.PyInt_FromLong for which integers compare by is - but remember that is an implementation detail so don't rely on it (always compare ints with ==):

>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = 257
>>> b = 257
>>> a is b
False

(from "is" operator behaves unexpectedly with integers)

For further motivation to always use ==, the following:

a = 300
b = 300
print(a is b)
print(a is 300)
def c(a): return a is 300
def d(a): return a is b
print(c(a))
print(d(a))

when saved to a file and run, prints True, True, False, and True...

thebjorn
  • 26,297
  • 11
  • 96
  • 138
  • Isn't it because the **is** operator checks whether they refer to the same object as opposed to equality? Because *44337068 is 44337068* is True. – dan-klasson Nov 09 '19 at 13:42
  • @dan-klasson yes, but same-object is only true for small integers in Python (because they're cached). It is also true for constants (in the same expression), as you've shown, however `44337068 is 44337067+1` is False. – thebjorn Nov 09 '19 at 13:44
  • Funny thing, if you are using python console: `>>> a = 300 >>> b = 300 >>> a is b >>> False` But if you run this using any IDE (pycharm, vsc) using same python binary as interpreter you get True. Why is that? – Paweł Bąkiewicz Nov 11 '19 at 10:53
  • @PawełBąkiewicz it's "because" `is` is not defined to return equality over integers, and you're bound to get surprising results if you try. I've expanded my answer with more examples. – thebjorn Nov 12 '19 at 09:39
0

If you attempted to do, for instance

 print(str(id(id(a))) + " " + str(id(id(a))))
In [54]: print(str(id(id(a))) + " " + str(id(id(a))))
2460780951888 2460780951888

In [55]: print(str(id(id(a))) + " " + str(id(id(a))))
2460780951472 2460780951472

In [56]: print(str(id(id(a))) + " " + str(id(id(a))))
2460782062320 2460782062320

In [57]: print(str(id(id(a))) + " " + str(id(id(a))))
2460780951888 2460780951888

In [58]: print(str(id(id(a))) + " " + str(id(id(a))))
2460782473392 2460782475664

that would return a new id for the large integer every time

As @thebjorn mentions, large integers are not cached by the python interpreter, only integers between -5 and 256 (in the CPython implementation) remain alive at all times.

Every time a large integer is reference a new object is created for it whereas for a small integer the same object keeps on being used (as an optimization) however this is not guaranteed to remain true on all python implementations.

Har
  • 3,727
  • 10
  • 41
  • 75