I was tinkering with string slicing in Python, and this is the code I came up with:
s = 'a string'
print(id(s[2:]), id(s[4:]))
print(id(s[2:])==id(s[4:]))
print(s[2:] is s[4:])
print(s[2:] is s[4:])
The following are the outcomes of the code:
439651916 439659216
True
False
False
My concern is how those string slices are maintained in memory, why do various slices of a string have the same id, and why do they produce ‘False’ when compared using the ‘is’ keyword with the same id?
The short version: this has nothing to do with slices.
In the code print(id(s[2:]), id(s[4:])), Python is free to compute one id value, throw away the corresponding slice (because there is nothing else that can use it), create the other slice, and find its id value.
id values, in the reference implementation, correspond to the memory addresses of the objects. Since the first slice was thrown away, it’s perfectly possible (and likely, with how the memory management is implemented) for the second slice to be created in the same place in memory, so it will have the same id value.
Similarly, the code print(id(s[2:])==id(s[4:])) only compares the id results. The slices can be thrown away immediately once the id is calculated, due to the reference-counting garbage collection. When the == is evaluated, the slices are already gone.
In the code print(s[2:] is s[4:]) however, the slices themselves are compared using is. That means they both have to exist in order for is to compare them. If two objects exist at the same time, they have to be stored in separate places in memory.