我遇到了这种奇怪的行为,它只发生在交互式Python会话中,但是当我编写脚本并执行它时却没有。
String是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'
长,但仍然具有相同的标识符。
答案 0 :(得分:6)
非常感谢@eryksun的更正!
这是因为Python中的机制调用interning
:
在“interned”字符串表中输入字符串并返回 interned string - 字符串本身或副本。实习字符串 有用的是在字典查找上获得一点性能 - 如果 字典中的密钥被中断,查找密钥被中断, 密钥比较(散列后)可以通过指针比较来完成 而不是字符串比较。通常,Python中使用的名称 程序自动实习,字典用于保存 模块,类或实例属性具有实习键。
版本2.3中更改:Interned字符串不是不朽的(就像它们一样 曾经在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 only interns strings without spaces而被实习,而不是因为我立即假设的长度:例如, ASCII字母,数字和下划线。
有关详细信息,您还可以参考Alex Martelli's answer here。