0

I have been reading the Python Data Model. The following text is taken from here:

Types affect almost all aspects of object behavior. Even the importance of object identity is affected in some sense: for immutable types, operations that compute new values may actually return a reference to any existing object with the same type and value, while for mutable objects this is not allowed. E.g., after a = 1; b = 1, a and b may or may not refer to the same object with the value one, depending on the implementation, but after c = []; d = [], c and d are guaranteed to refer to two different, unique, newly created empty lists. (Note that c = d = [] assigns the same object to both c and d.)

So, it mentions that, for immutable types, operations that compute new values may actually return a reference to an existing object with same type and value. So, I wanted to test this. Following is my code:

a = (1,2,3)
b = (1,2)
c = (3,)
k = b + c
print(id(a))
>>> 2169349869720    
print(id(k))
>>> 2169342802424

Here, I did an operation to compute a new tuple that has same the value and type as a. But I got an object referencing to different id. This means I got an object which references different memory than a. Why is this?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
rawwar
  • 4,834
  • 9
  • 32
  • 57
  • 2
    Note "*may* actually return" - it's not guaranteed, it would likely be *less* efficient for Python to look through the existing tuples to find out if one that's the same as the one your operation creates already exists and reuse it than it would to just create a new one. – jonrsharpe Mar 23 '20 at 11:59
  • @jonrsharpe- So, in what cases python decides to look up and return the same object – rawwar Mar 23 '20 at 12:00
  • That's implementation dependent, and may vary between compile and run time. In CPython, for example, integers between -5 and 256 (IIRC) are "interned" and reused, so any operation you perform that gives you e.g. 10 returns the same object. Strings are another candidate, strings that represent identifiers are interned. – jonrsharpe Mar 23 '20 at 12:02
  • See https://stackoverflow.com/q/306313/3001761, https://stackoverflow.com/q/15541404/3001761 – jonrsharpe Mar 23 '20 at 12:03
  • Ah, This one. Now, i get that – rawwar Mar 23 '20 at 12:05
  • So, this would never happen in cases of containers. Always applicable to basic data types – rawwar Mar 23 '20 at 12:06
  • 1
    Tuples (and e.g. frozensets) are immutable containers, so it could happen for them depending on the implementation. But this isn't behaviour to rely on, which is why you e.g. compare strings by equality not identity. – jonrsharpe Mar 23 '20 at 12:10
  • Thanks. I think i understand this now. – rawwar Mar 23 '20 at 12:12
  • 1
    In some cases CPython even swaps one for the other for efficiency, e.g. the peephole optimisations referenced in https://stackoverflow.com/questions/25368337/tuple-or-list-when-using-in-in-an-if-clause that convert list -> tuple and set -> frozenset. – jonrsharpe Mar 23 '20 at 12:13

1 Answers1

0

Answering the question based on comments from @jonrsharpe

Note "may actually return" - it's not guaranteed, it would likely be less efficient for Python to look through the existing tuples to find out if one that's the same as the one your operation creates already exists and reuse it than it would to just create a new one.

rawwar
  • 4,834
  • 9
  • 32
  • 57