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)