sys.intern() 无法在切片时实习字符串

sys.intern() failing to intern a string upon slicing

为什么 sys.intern() 无法实习这个字符串?

>>> from sys import intern
>>> "abcd"[:-1] == "abc"
True
>>> "abcd"[:-1] is "abc"
False
>>> intern("abc")
'abc'
>>> "abcd"[:-1] is "abc"
False  # Expected True

(在 CPython 3.7.4 上)

字符串字面量已经被驻留,它是您需要手动驻留的计算表达式。

from sys import intern
print("abcd"[:-1] is "abc")  # False
print(intern("abcd"[:-1]) is "abc")  # True
print("abcd"[:-1] is "abc")  # False

intern 并不意味着 'whenever this string gets produced anywhere in the program change it to the interned reference',它只是 returns 给定字符串的内部引用。

s1 = "abc"
s2 = "abc"
s3 = "abcd"[:-1]
s4 = intern(s3)
for s in [s1, s2, s3, s4]:
  print(id(s))
140002991598512
140002991598512
140002990838576
140002991598512

你的期望是错误的。名称、字符串常量和类似内容在创建代码对象时 (here) 而不是在创建任何字符串对象时被保留。

"abcd"[:-1] 的字符串是在 运行 期间创建的,因此没有被保留。理论上,如果优化器会在编译期间评估这个表达式,它可以被保留,例如

>>> "a"*5 is "aaaaa"  #True

但这只是一个实现细节,例如

>>> "a"*4097

将不再在编译期间求值,因此不会被保留。