Why is sys.intern() failing to intern this string?
>>> from sys import intern
>>> "abcd"[:-1] == "abc"
True
>>> "abcd"[:-1] is "abc"
False
>>> intern("abc")
'abc'
>>> "abcd"[:-1] is "abc"
False # Expected True
(on CPython 3.7.4)
Why is sys.intern() failing to intern this string?
>>> from sys import intern
>>> "abcd"[:-1] == "abc"
True
>>> "abcd"[:-1] is "abc"
False
>>> intern("abc")
'abc'
>>> "abcd"[:-1] is "abc"
False # Expected True
(on CPython 3.7.4)
String literals are already interned, it's computed expressions that you'd need to intern manually.
from sys import intern
print("abcd"[:-1] is "abc") # False
print(intern("abcd"[:-1]) is "abc") # True
print("abcd"[:-1] is "abc") # False
intern doesn't mean 'whenever this string gets produced anywhere in the program change it to the interned reference', it just returns the interned reference for the string it's given.
s1 = "abc"
s2 = "abc"
s3 = "abcd"[:-1]
s4 = intern(s3)
for s in [s1, s2, s3, s4]:
print(id(s))
140002991598512
140002991598512
140002990838576
140002991598512
Your expectations are wrong. Names, string-constants and similar are interned when the code-object is created (here) and not when any string-object is created.
The string for "abcd"[:-1] is created during the run time and thus not interned. Theoretically, if optimizer would evaluate this expression during the compile time, it could be interned, as it happens for example with
>>> "a"*5 is "aaaaa" #True
But it is just an impelementation detail, for example
>>> "a"*4097
would no longer be evaluated during the compile time and thus not interned.