两个字符串变量被设置为相同的值。s1 == s2总是返回True,但s1 = s2有时返回False。
如果我打开我的Python解释器,并做同样的比较,它成功了:
>>> s1 = 'text'
>>> s2 = 'text'
>>> s1 is s2
True
为什么会这样?
两个字符串变量被设置为相同的值。s1 == s2总是返回True,但s1 = s2有时返回False。
如果我打开我的Python解释器,并做同样的比较,它成功了:
>>> s1 = 'text'
>>> s2 = 'text'
>>> s1 is s2
True
为什么会这样?
当前回答
这里的其他答案是正确的:is用于恒等比较,而==用于相等比较。由于您关心的是相等性(两个字符串应该包含相同的字符),在这种情况下,is操作符是错误的,您应该使用==代替。
原因是交互工作的(大多数)字符串字面量是默认的。从维基百科:
Interned strings speed up string comparisons, which are sometimes a performance bottleneck in applications (such as compilers and dynamic programming language runtimes) that rely heavily on hash tables with string keys. Without interning, checking that two different strings are equal involves examining every character of both strings. This is slow for several reasons: it is inherently O(n) in the length of the strings; it typically requires reads from several regions of memory, which take time; and the reads fills up the processor cache, meaning there is less cache available for other needs. With interned strings, a simple object identity test suffices after the original intern operation; this is typically implemented as a pointer equality test, normally just a single machine instruction with no memory reference at all.
因此,当你在程序中有两个具有相同值的字符串字面量(字面上输入到程序源代码中的单词,被引号包围)时,Python编译器将自动对字符串进行替换,使它们都存储在相同的内存位置。(请注意,这种情况并不总是发生,发生这种情况的规则相当复杂,所以请不要在生产代码中依赖这种行为!)
由于在交互式会话中,两个字符串实际上存储在相同的内存位置,因此它们具有相同的标识,因此is操作符可以正常工作。但是如果您通过其他方法构造一个字符串(即使该字符串包含完全相同的字符),那么字符串可能是相等的,但它不是相同的字符串——也就是说,它具有不同的标识,因为它存储在内存中的不同位置。
其他回答
根据我有限的Python使用经验,is用于比较两个对象,以确定它们是否是相同的对象,而不是具有相同值的两个不同对象。==用于确定两个值是否相同。
这里有一个很好的例子:
>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True
s1是Unicode字符串,s2是普通字符串。它们不是相同的类型,但它们的值相同。
==运算符测试值等价性。is操作符测试对象的身份,Python测试两者是否真的是相同的对象(即,在内存中存在相同的地址)。
>>> a = 'banana'
>>> b = 'banana'
>>> a is b
True
在这个例子中,Python只创建了一个字符串对象,并且a和b都指向它。原因是Python内部缓存和重用一些字符串作为优化。内存中实际上只有一个字符串'banana',由a和b共享。为了触发正常行为,你需要使用更长的字符串:
>>> a = 'a longer banana'
>>> b = 'a longer banana'
>>> a == b, a is b
(True, False)
当你创建两个列表时,你会得到两个对象:
>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a is b
False
在这种情况下,我们会说这两个列表是等价的,因为它们有相同的元素,但不相同,因为它们不是同一个对象。如果两个对象是相同的,它们也是等效的,但如果它们是等效的,它们就不一定相同。
如果a指向一个对象,你赋值b = a,那么两个变量指向同一个对象:
>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
参考:Allen B. Downey的《Python 2e》
is是身份测试,==是相等测试(请参阅Python文档)。
在大多数情况下,如果a是b,那么a == b。但也有例外,例如:
>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False
所以,你只能在同一性测试中使用is,而不是相等性测试。
我相信这就是所谓的“被拘禁的”字符串。Python做到了这一点,Java也是如此,C和c++在优化模式下编译时也是如此。
如果使用两个相同的字符串,就不会因为创建两个字符串对象而浪费内存,所有具有相同内容的合并字符串都会指向相同的内存。
这将导致Python“is”操作符返回True,因为具有相同内容的两个字符串指向同一个字符串对象。这在Java和C中也会发生。
不过,这只对节省内存有用。您不能依赖它来测试字符串是否相等,因为各种解释器、编译器和JIT引擎并不总是能做到这一点。
基本概念,我们必须清楚,在处理这个问题时,是理解is和==之间的区别。
is将比较内存位置。如果id(a)==id(b),则a是b返回true,否则返回false。
所以,我们可以说is是用来比较内存位置的。然而,
==用于相等性测试,这意味着它只比较结果值。下面显示的代码可以作为上述理论的一个例子。
Code
对于字符串字面值(未分配给变量的字符串),内存地址将与图中所示相同。所以,id (a) (b) = = id。剩下的是不言自明的。