2

If I am not mistaken a is b should return True if a and b point to the same object. With two equal lists it returns False because the lists are two different lists. I thought that immutable objects didn't have this problem but when I put in:

a = (1, 2, 3)
b = (1, 2, 3)
a is b #returns false

I thought that this should return True since a and b point to an immutable object that has the same value. Why isn't a pointing to the same object as b when I use tuples?

glibdud
  • 7,550
  • 4
  • 27
  • 37
Brendan Mesters
  • 203
  • 1
  • 10
  • 4
    Not all immutable objects are interned. – Dan D. Jan 26 '17 at 13:19
  • http://pythontutor.com/visualize.html#code=a%20%3D%20(1,%202,%203%29%0Ab%20%3D%20(1,%202,%203%29%0Aa%20is%20b%20%23returns%20false&cumulative=true&curInstr=3&heapPrimitives=true&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false – Chris_Rands Jan 26 '17 at 13:22
  • 1
    This is related: http://stackoverflow.com/q/6934202/4996248 – John Coleman Jan 26 '17 at 13:23

2 Answers2

5

Your a and b do not point to the same object (you create two individual tuples); you can inspect that with id(a) or -- as you did -- with a is b.

a == b

on the other hand will be True.

If you want them to point to the same object you could do

a = b = (1, 2, 3)

Now a is b is True.

None of this has to do with mutability or immutability; it would work the same if you took lists instead of tuples.

You can visualize your code pythontutor to see what is happening.

Python does intern some strings and some small integers (e.g. a=0; b=0; a is b yields True) but not all immutables are interned. Furthermore you should not rely on that, rather consider it an implementation detail.

glibdud
  • 7,550
  • 4
  • 27
  • 37
hiro protagonist
  • 44,693
  • 14
  • 86
  • 111
2

Your code should never rely on the details on what gets does and doesn't get interned. It is completely implementation dependent, and could change from point release to point release.

Interning is designed solely to be an optimization to reduce memory usage, and you are correct that in principle any literal of an immutable value could be interned, but that's only actually done in the most trivial of cases.

One likely reason that tuples aren't interned is that they're not deeply immutable. If you put something mutable inside them (such as ({}, [])), interning them could lead to incorrect behavior, as modifying one could modify the other.

You could of course check whether a tuple contains only immutable objects, but tuples can be nested arbitrarily deeply, so you'd have to do work to verify that a tuple only (transitively) contains immutable objects, and that's really not worth it, because you can always "manually intern" them if you want.

a = 1, 2, 3
b = a
Kevin
  • 1,870
  • 2
  • 20
  • 22