4

Can someone explain me this behaviour?

a = 'Test'
b = 'Test'
print(a is b)  # True

I have expected the result to be False, because a and b are different references. The shown result I would have expect when using the equal-operator (==) for comparing on value-equality.

The is-operator is for to compare reference-equality? Or have I get that wrong?

What's the reason for the shown behaviour?

cluster1
  • 4,968
  • 6
  • 32
  • 49
  • 2
    The interpreter is allowed to detect multiple identical string literals in your code and use one string object for them all. In this case evidently the interpreter has done that, and `a` and `b` both reference the same object. – khelwood Oct 25 '20 at 09:13
  • @khelwood Ah, okay. That would mean that it is similar to Java, where you have a String-pool. – cluster1 Oct 25 '20 at 09:17

1 Answers1

5

In short:

== is for value equality and is is for reference equality (same as id(a)==id(b)). Python caches small objects(small ints, strs, etc) to save space (feature that has been since py2).

My original detailed answer with examples:

Because they are exactly the same!

is will return True if two variables point to the same object, you can check the id to see the truth!

Try this:

a = 'Test'
b = 'Test'
print(a is b) 
print(id(a),id(b))

My output was:

True
140586094600464 140586094600464

So to save space Python will assign the pointer same location until a change is a made

Example:

a = 'Test'
b = 'Test'
print(a is b) 
print(id(a),id(b))
a = 'Test'
b += 'Changed'
print(a is b) 
print(id(a),id(b))
True
140586094600464 140586094600464
False
140586094600464 140585963428528

Once you make a change, strings being immutable will get new location in memory!

If this was something like list, which is mutable even if they are same they will get separate location, so changes can be made!

#mutable
a= [1,2]
b= [1,2]
print(a is b) 
print(id(a),id(b))
a[0] = -1
b[1] = -2
print(a is b) 
print(id(a),id(b))
False
140586430241096 140585963716680
False
140586430241096 140585963716680

Int eg:

a=100 
b=100
print(a is b) 
print(id(a),id(b))
True
10917664 10917664
Kuldeep Singh Sidhu
  • 3,748
  • 2
  • 12
  • 22
  • Really? If we modify b, a won't change and vice versa. So how they are same reference? – Wasif Oct 25 '20 at 09:12
  • 4
    You cannot modify either. Strings are immutable. – user2390182 Oct 25 '20 at 09:12
  • 2
    "until a change is a made" this part is misleading. Python does not redirect the pointer when one of the strings is "changed". The pointer simply gets pointed to a different string. – tobias_k Oct 25 '20 at 09:16
  • But isn't that made evident by this statement "Once you make a change, strings being immutable will get new location in memory!" @tobias_k ? – S M Vaidhyanathan Oct 25 '20 at 09:17
  • 2
    Also, "Because they are exactly the same!" is a gross simplification and does not really answer why and when exactly strings (or numbers, for that matter) are pooled. E.g. if you do `c = a.title()`, c is also "exactly the same" as `a`, but `a` `is` not `c`. Or if you assign both `a` and `b` as `"a" * 5000` – tobias_k Oct 25 '20 at 09:18
  • 2
    @SMVaidhyanathan No. The *string* is the in-memory object and it undergoes no change whatsoever (until garbage collected) and it certainly does not get a new location. What changes is the binding of the variable, which of itself has no concept of being a string. – user2390182 Oct 25 '20 at 09:28