为什么用'=='或'is'比较字符串有时结果不同?

1318 投票
15 回答
1657523 浏览
提问于 2025-04-15 14:43

有两个字符串变量,它们的值是一样的。用 s1 == s2 比较时,总是会返回 True,但是用 s1 is s2 比较时,有时候会返回 False

如果我在 Python 解释器里做同样的 is 比较,它却成功了:

>>> s1 = 'text'
>>> s2 = 'text'
>>> s1 is s2
True

这是为什么呢?

15 个回答

123

is 这个关键词用来检查两个对象是否是同一个对象,而 == 是用来比较两个对象的值是否相等。

如果你使用 is,那么只有当这两个对象完全相同(就是同一个对象)时,结果才会是对的(true)。但是如果你用 ==,只要这两个对象的值相同,结果就会是对的(true)。

661

这里其他的回答是对的:is 用来比较两个对象是否是同一个,而 == 用来比较两个对象的内容是否相同。因为你关心的是内容是否相同(两个字符串应该包含相同的字符),所以在这种情况下,使用 is 是错误的,你应该使用 ==

之所以在交互式环境中 is 有效,是因为(大多数)字符串字面量默认是被 内存共享的。来自维基百科的解释:

内存共享的字符串可以加快字符串比较的速度,而字符串比较有时会成为应用程序的性能瓶颈(比如编译器和动态编程语言的运行时),这些应用程序严重依赖于使用字符串作为键的哈希表。如果没有内存共享,检查两个不同的字符串是否相等就需要逐个检查两个字符串的每个字符。这是比较慢的,原因有几个:首先,它的时间复杂度是 O(n),与字符串的长度成正比;其次,通常需要从多个内存区域读取数据,这会耗费时间;最后,读取操作会占用处理器的缓存,导致可用的缓存减少。使用内存共享的字符串后,经过初始的内存共享操作后,只需进行简单的对象身份测试;这通常实现为指针相等测试,通常只需要一条机器指令,根本不需要访问内存。

所以,当你在程序中有两个字符串字面量(就是直接在代码中输入的字符串,用引号括起来)且它们的值相同,Python 编译器会自动将这两个字符串进行内存共享,使它们存储在同一个内存位置。(注意,这并不是 总是 会发生的,发生的规则相当复杂,所以请不要在生产代码中依赖这种行为!)

因为在你的交互式会话中,这两个字符串实际上存储在同一个内存位置,所以它们有相同的 身份,因此 is 操作符的表现是符合预期的。但是如果你通过其他方法构造一个字符串(即使这个字符串包含的字符 完全 一样),那么这个字符串可能是 相等的,但它并不是 同一个字符串——也就是说,它有不同的 身份,因为它存储在内存中的不同位置。

1677

is 是用来检查两个东西是不是同一个东西,而 == 是用来检查两个东西的内容是否相等。你代码里的情况可以在解释器中这样理解:

>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False

所以,它们不一样也就不奇怪了,对吧?

换句话说:a is b 就相当于 id(a) == id(b)

撰写回答