两个字符串变量被设置为相同的值。s1 == s2总是返回True,但s1 = s2有时返回False。

如果我打开我的Python解释器,并做同样的比较,它成功了:

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

为什么会这样?


当前回答

实际上,is操作符检查是否相同,而==操作符检查是否相等。

从语言参考:

Types affect almost all aspects of object behavior. Even the importance of object identity is affected in some sense: for immutable types, operations that compute new values may actually return a reference to any existing object with the same type and value, while for mutable objects this is not allowed. E.g., after a = 1; b = 1, a and b may or may not refer to the same object with the value one, depending on the implementation, but after c = []; d = [], c and d are guaranteed to refer to two different, unique, newly created empty lists. (Note that c = d = [] assigns the same object to both c and d.)

因此,从上面的语句中,我们可以推断出字符串是不可变类型,当使用"is"检查时可能会失败,而当使用"is"检查时可能会成功。

同样适用于int和tuple,它们也是不可变类型。

其他回答

最后需要注意的是,你可以使用sys.intern函数来确保你得到的是同一个字符串的引用:

>>> from sys import intern
>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

正如在前面的回答中指出的,您不应该使用is来确定字符串的相等性。但这可能有助于了解您是否有一些奇怪的要求使用is。

注意,intern函数曾经是Python 2的内置函数,但在Python 3中被移到了sys模块中。

这里的其他答案是正确的: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操作符可以正常工作。但是如果您通过其他方法构造一个字符串(即使该字符串包含完全相同的字符),那么字符串可能是相等的,但它不是相同的字符串——也就是说,它具有不同的标识,因为它存储在内存中的不同位置。

基本概念,我们必须清楚,在处理这个问题时,是理解is和==之间的区别。

is将比较内存位置。如果id(a)==id(b),则a是b返回true,否则返回false。

所以,我们可以说is是用来比较内存位置的。然而,

==用于相等性测试,这意味着它只比较结果值。下面显示的代码可以作为上述理论的一个例子。

Code

对于字符串字面值(未分配给变量的字符串),内存地址将与图中所示相同。所以,id (a) (b) = = id。剩下的是不言自明的。

is是身份测试,==是相等测试(请参阅Python文档)。

在大多数情况下,如果a是b,那么a == b。但也有例外,例如:

>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False

所以,你只能在同一性测试中使用is,而不是相等性测试。

Is是同一性测试,==是相等性测试。这意味着is是一种检查两件事物是否相同或等价的方法。

假设你有一个简单的person对象。如果它的名字是“Jack”,而且是“23岁”,那么它就相当于另一个23岁的Jack,但它不是同一个人。

class Person(object):
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def __eq__(self, other):
       return self.name == other.name and self.age == other.age

jack1 = Person('Jack', 23)
jack2 = Person('Jack', 23)

jack1 == jack2 # True
jack1 is jack2 # False

他们年龄相同,但他们不是同一个人。一个字符串可能与另一个字符串等价,但它不是同一个对象。