非常感谢@eryksun 的更正!
interning
这是因为Python中的机制调用:
在“interned”字符串表中输入 string 并返回 interned string - 它是字符串本身或副本。留置字符串对于在字典查找中获得一点性能很有用——如果字典中的键被留存,并且查找键被留存,则键比较(在散列之后)可以通过指针比较而不是字符串比较来完成。通常,Python 程序中使用的名称是自动实习的,用于保存模块、类或实例属性的字典具有实习键。
在 2.3 版更改: 内部字符串不是不朽的(就像它们曾经在 Python 2.2 及之前的版本中一样);您必须保留对 intern() 的返回值的引用才能从中受益。
CPython将自动缩短某些字符串(1 个字母字符串、关键字、已分配空格的字符串)以提高查找速度和比较速度:例如,'dog' is 'dog'
将是指针比较而不是完整字符串比较。但是,所有(更长的)字符串的自动实习需要更多的内存,这并不总是可行的,因此它们可能不会共享相同的标识,这会导致结果id()
不同,例如:
# different id when not assigned
In [146]: id('dog')
Out[146]: 4380547672
In [147]: id('dog')
Out[147]: 4380547552
# if assigned, the strings will be interned (though depends on implementation)
In [148]: a = 'dog'
In [149]: b = 'dog'
In [150]: id(a)
Out[150]: 4380547352
In [151]: id(b)
Out[151]: 4380547352
In [152]: a is b
Out[152]: True
对于整数,至少在我的机器上,CPython 会自动实习到 256 个:
In [18]: id(256)
Out[18]: 140511109257408
In [19]: id(256)
Out[19]: 140511109257408
In [20]: id(257)
Out[20]: 140511112156576
In [21]: id(257)
Out[21]: 140511110188504
感谢@eryksun 更新:在这种情况下,字符串'a string'
没有被实习,因为CPython 只实习没有空格的字符串,而不是因为我立即假设的长度:例如,ASCII 字母、数字和下划线。
有关更多详细信息,您还可以在此处参考Alex Martelli 的回答。