Thanks for reading. I think you need to take a look at the concept of interning in python and also the compiler optimisation. The whole concept is an article by itself so I will try to keep my answer short.
If you see your answer the id of the final_string still changes at few iterations. But there is no specific pattern on how or where it changes.
You have 3 different memory addresses.
4343216560, 4343465968 and 4343493056. This shows that a new object does get created. But how and when depends on the compiler optimisation.
The compiler reuses some of the memory space used for literals and stores them. This behaviour applies for REPL(interactive mode) as well. Python compiler will also intern any Python string stored as a constant(CPython), provided it looks enough like a valid identifier.
A valid identifier is a string that matches this criterion [a-zA-Z0-9_]. Since our string satisfies this, may be the compiler reuses the memory.In addition to that, the length of the string being concatenated also matters.
Having said all that we cannot define a concrete pattern as to when a new string object will be created .
For more details , please have a look at the below stack overflow answer.
It's the same reason why python caches integers from -5 to 256 though integers are immutable in python.
a = 1
b = 1
print(a is b)
Try running this in an interactive mode and print the ids of a and b. Both will point to the same memory. However change the value of a and b to 257(or any value above). Both will have different memory locations though they are immutable.