将unicode对象与字符串对象进行比较时出现奇怪的行为

时间:2013-12-07 06:56:47

标签: python python-2.7 unicode

比较python中的两个字符串时,它工作正常,当比较string对象和unicode对象时,它会按预期失败但是将string对象与转换后的unicode进行比较< em> (unicode --> str) 对象失败

演示:

按预期工作:

>>> if 's' is 's': print "Hurrah!"
... 
Hurrah!

非常是啊:

>>> if 's' is u's': print "Hurrah!"
... 

不期望:

>>> if 's' is str(u's'): print "Hurrah!"
... 

为什么当这两个类型属于同一类时,第三个例子是否按预期工作?

>>> type('s')
<type 'str'>

>>> type(str(u's'))
<type 'str'>

3 个答案:

答案 0 :(得分:12)

请勿使用is,请使用==。您正在比较对象是否具有相同的标识,而不是它们是否相等。当然,如果它们是相同的对象,它们将是相等的(==),但如果它们相等,则它们不一定是同一个对象。

第一个工作的事实是CPython的实现细节。小字符串,因为它们是不可变的,可以由解释器实现。每次将字符串"s"放入源代码中时,Cpython都会重用相同的对象。但是,显然str("s")返回一个具有相同值的新字符串。这并不奇怪。


你可能会问自己,“为什么要对字符串's'进行实际操作?”。这是一个合理的问题。毕竟,它是一个短小的字符串 - 在你的源代码中有多少内存可以有多个副本?答案(我认为)是因为字典查找。由于字符串作为键的dicts在python中非常常见,因此当指针比较返回false时,可以通过快速指针比较(回落到较慢的strcmp)来加快键的哈希函数/等式检查。 p>

答案 1 :(得分:3)

is运算符用于比较两个操作数的内存位置。由于字符串是不可变的,'s''s'占用内存中的相同位置。

由于在python2.7中处理unicode的方式,u's''s'以相同的方式/位置存储。因此,它们占据相同的内存位置。因此's' is u's'评估为True
正如@mgilson指出的那样,'s'u's'属于不同的类型,因此不占用相同的内存位置,导致's' is u's'评估为False

但是,当您调用str(u's')时,会创建并返回一个新字符串。这个新字符串因为重新创建而存在于内存中的新位置,这就是is比较失败的原因。

您真正想要的是检查它们是等效的字符串,因此请使用==

In [1]: 's' == u's'
Out[1]: True

In [2]: 's' == 's'
Out[2]: True

In [3]: 's' == str(u's')
Out[3]: True

答案 2 :(得分:2)

使用==进行值比较,使用is进行参考比较。如果对象具有相同的id,则评估为True,否则与str()一样,id会被更改,因此您获得False