Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using 'is' operator to compare two string slices in python

I was experimenting with string slicing in python, and this is my code:

s = 'a string'
print(id(s[3:]), id(s[5:]))
print(id(s[3:])==id(s[5:]))
print(s[3:] is s[5:])
print(s[3:] is s[3:])

The code produced the following results:

4396519216 4396519216
True
False
False

My question is how those string slices are stored in memory, why do different slices of a string have the same id, and with the same id, why do they yield 'False' when compared using 'is' keyword?

like image 313
zvzv1919 Avatar asked Dec 23 '22 17:12

zvzv1919


2 Answers

Because you don't save the slices in a variable (or anywhere) after the call to id, their lifetime is actually non-overlapping so the id may be reused.
from id()'s docs:

Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

note that because is needs them both to live, they probably get different ids, but when you call id on each one individually it can be destructed after id returns, and the comparison itself is done on the int returned from the function.

if you save them to dummy variables, you will get results that are less surprising in my opinion:

s = 'a string'
s3 = s[3:]
s5 = s[5:]
print(id(s3), id(s5))
print(id(s3)==id(s5))
print(s3 is s5)
print(s3 is s3)

Output:

25517664 25517728
False
False
True
like image 116
Adam.Er8 Avatar answered Jan 10 '23 06:01

Adam.Er8


The == syntax is comparing the values of the String objects. Technically, it is running the __eq__ method on the String object.

The is syntax compares the objects, not the objects value. When you take a slice of a string you are creating a new object

>>> print(id(s[3:]))
139911809265200
>>> print(id(s[3:]))
139911809262384

There is something and strange happening with values being returned from the id function that I don't understand. However, this id issue is a separate thing that doesn't affect how the == and is syntax works

>>> (id(s[3:]), id(s[3:]), id(s[3:]), id(s[3:]))
(139911809265200, 139911809265200, 139911809265200, 139911809265200)
>>> (id(s[3:]), id(s[3:]), id(s[3:]), id(s[3:]))
(139911809262384, 139911809262384, 139911809262384, 139911809262384)
>>> (id(s[3:]), id(s[3:]), id(s[3:]), id(s[3:]))
(139911809265200, 139911809265200, 139911809265200, 139911809265200)
>>> (id(s[3:]), id(s[3:]), id(s[3:]), id(s[3:]))
(139911809262384, 139911809262384, 139911809262384, 139911809262384)

>>> a = id(s[3:])
>>> id(a)
139911809261520
>>> b = id(s[3:])
>>> id(b)
139911809261424
>>> c = id(s[3:])
>>> id(c)
139911809261360


>>> (id(a), id(b), id(c))
(139911809261520, 139911809261424, 139911809261360)
>>> (id(a), id(b), id(c))
(139911809261520, 139911809261424, 139911809261360)
>>> (id(s[3:]), id(s[3:]), id(s[3:]))
(139911809265200, 139911809265200, 139911809265200)
>>> (id(s[3:]), id(s[3:]), id(s[3:]))
(139911809263472, 139911809263472, 139911809263472)
>>> (id(s[3:]), id(s[3:]), id(s[3:]))
(139911809265200, 139911809265200, 139911809265200)

like image 22
cad106uk Avatar answered Jan 10 '23 06:01

cad106uk