我遇到了这种奇怪的行为,这种行为仅在交互式Python会话中发生,而在编写脚本并执行时却没有。
在Python中,字符串是不可变的数据类型,因此:
>>> s2='string' >>> s1='string' >>> s1 is s2 True
现在,奇怪的部分:
>>> s1='a string' >>> s2='a string' >>> s1 is s2 False
我已经看到,字符串中包含空格会导致此行为。如果将其放在脚本中并运行,则在两种情况下结果均为True。
有人对此有任何线索吗?谢谢。
编辑:
好的,上面的问题和答案给出了一些想法。现在这是另一个实验:
>>> s2='astringbstring' >>> s1='astringbstring' >>> s1 is s2 True
在这种情况下,字符串肯定比更长'a string',但仍具有相同的标识符。
'a string'
非常感谢@eryksun的更正!
这是由于interningPython中的机制调用:
interning
在“ interned”字符串表中输入string并返回被中断的字符串–它是字符串本身或副本。插入字符串对于提高字典查找的性能很有用–如果字典中的键被插入,并且查找键被插入,则键比较(散列后)可以通过指针比较而不是字符串比较来完成。通常,Python程序中使用的名称会被自动插入,并且用于保存模块,类或实例属性的字典具有插入键。 在版本2.3中进行了更改:内联字符串不是不朽的(就像它们曾经在Python 2.2及之前的版本中一样);您必须保留对intern()返回值的引用,以从中受益。
在“ interned”字符串表中输入string并返回被中断的字符串–它是字符串本身或副本。插入字符串对于提高字典查找的性能很有用–如果字典中的键被插入,并且查找键被插入,则键比较(散列后)可以通过指针比较而不是字符串比较来完成。通常,Python程序中使用的名称会被自动插入,并且用于保存模块,类或实例属性的字典具有插入键。
在版本2.3中进行了更改:内联字符串不是不朽的(就像它们曾经在Python 2.2及之前的版本中一样);您必须保留对intern()返回值的引用,以从中受益。
CPython 会自动实习 短 某些字符串(1个字母字符串,关键字,没有分配空格的字符串)以提高查找速度和比较速度:例如,'dog' is 'dog'将是指针比较而不是完整的字符串比较。但是,对所有(较长)字符串的自动实习需要更多的内存,这并不总是可行的,因此它们可能不会共享相同的标识,从而导致结果id()不同,例如:
'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字母,数字和下划线。