两个字符串变量被设置为相同的值。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是身份测试,==是相等测试(请参阅Python文档)。
在大多数情况下,如果a是b,那么a == b。但也有例外,例如:
>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False
所以,你只能在同一性测试中使用is,而不是相等性测试。
其他回答
我认为这与这样一个事实有关,当'is'比较的结果为false时,使用了两个不同的对象。如果它的计算值为true,这意味着它在内部使用相同的对象,而不是创建一个新的对象,可能是因为你在不到2秒的时间内创建了它们,并且在优化和使用相同的对象之间没有很大的时间间隔。
这就是为什么你应该使用相等操作符==,而不是is,来比较字符串对象的值。
>>> s = 'one'
>>> s2 = 'two'
>>> s is s2
False
>>> s2 = s2.replace('two', 'one')
>>> s2
'one'
>>> s2 is s
False
>>>
在这个例子中,我创建了s2,它是一个不同的字符串对象,之前等于'one',但它与s不是同一个对象,因为解释器没有使用相同的对象,因为我最初没有将它赋值给'one',如果我有的话,它会使它们成为相同的对象。
Is是同一性测试,==是相等性测试。在你的代码中发生的事情将在解释器中模拟,就像这样:
>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False
所以,难怪它们不一样,对吧?
换句话说,a等于b等于id(a) == id(b)
==运算符测试值等价性。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》
将比较内存位置。它用于对象级比较。
==将比较程序中的变量。它用于在值级别上进行检查。
是否检查地址级别等价性
==检查值级别是否等价
最后需要注意的是,你可以使用sys.intern函数来确保你得到的是同一个字符串的引用:
>>> from sys import intern
>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True
正如在前面的回答中指出的,您不应该使用is来确定字符串的相等性。但这可能有助于了解您是否有一些奇怪的要求使用is。
注意,intern函数曾经是Python 2的内置函数,但在Python 3中被移到了sys模块中。