Python 为什么使用'==';或';是';有时会产生不同的结果?
我有一个Python程序,其中两个变量被设置为值Python 为什么使用'==';或';是';有时会产生不同的结果?,python,string,comparison,identity,equality,Python,String,Comparison,Identity,Equality,我有一个Python程序,其中两个变量被设置为值“public”。在条件表达式中,比较var1是var2,但如果将其更改为var1==var2,则返回True 现在,如果我打开Python解释器并进行相同的“是”比较,它就会成功 >>> s1 = 'public' >>> s2 = 'public' >>> s2 is s1 True 这里我遗漏了什么?关键字是对对象身份的测试,而=是一个值比较 如果使用is,则当且仅当对象是同一对象时,结
“public”
。在条件表达式中,比较var1是var2
,但如果将其更改为var1==var2
,则返回True
现在,如果我打开Python解释器并进行相同的“是”比较,它就会成功
>>> s1 = 'public'
>>> s2 = 'public'
>>> s2 is s1
True
这里我遗漏了什么?关键字是对对象身份的测试,而
=
是一个值比较
如果使用
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 is b
相当于id(a)==id(b)
根据我对python有限的经验,is
用于比较两个对象,以确定它们是否是相同的对象,而不是具有相同值的两个不同对象<代码>=用于确定值是否相同
下面是一个很好的例子:
>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True
s1
是unicode字符串,s2
是普通字符串。它们不是相同的类型,而是相同的值。我相信这就是所谓的“内部”字符串。Python也这样做,java也是如此,编译时,C和C++也是这样的。
如果您使用两个相同的字符串,那么所有具有相同内容的插入字符串都指向相同的内存,而不是通过创建两个字符串对象来浪费内存
这导致Python“is”操作符返回True,因为两个具有相同内容的字符串指向同一个字符串对象。这在Java和C中也会发生
不过,这只对节省内存有用。您不能依靠它来测试字符串是否相等,因为各种解释器、编译器和JIT引擎都不能始终做到这一点。这里的其他答案是正确的:
is
用于标识比较,而=
用于相等比较。因为您关心的是相等(两个字符串应该包含相同的字符),所以在这种情况下,is
运算符完全错误,您应该使用==
is
以交互方式工作的原因是(大多数)字符串文本默认为。来自维基百科:
内接琴弦加速琴弦
比较,有时是一种比较
应用程序中的性能瓶颈
(例如编译器和动态
编程语言运行时)的
严重依赖具有
字符串键。没有实习,,
检查两个不同的字符串
平等包括检查每一个方面
两个字符串的字符。这是
慢有几个原因:它是
固有的O(n)长度
串;它通常需要读取
来自记忆的几个区域,其中
花时间;阅读填满了整个世界
处理器缓存,这意味着
缓存可用于其他需要。具有
插入字符串,一个简单的对象
测试完成后,身份测试就足够了
原始实习操作;这是
通常作为指针实现
平等测试,通常只有一个
无存储器的机器指令
参考资料
因此,当您的程序中有两个具有相同值的字符串文本(字面上输入到程序源代码中的单词,用引号括起来)时,Python编译器将自动将字符串插入内存,使它们都存储在相同的内存位置。(请注意,这种情况并不总是发生,发生这种情况的规则非常复杂,因此请不要在生产代码中依赖这种行为!)
由于在交互式会话中,两个字符串实际上存储在同一个内存位置,因此它们具有相同的标识,因此
is
操作符按预期工作。但是,如果您使用其他方法构造字符串(即使该字符串包含完全相同的字符),则该字符串可能相等,但它不是相同的字符串--也就是说,它具有不同的标识,因为它存储在内存中的不同位置。最后需要注意的是,您可以使用该函数确保获得对同一字符串的引用:
>>> from sys import intern
>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True
>>> a = 'banana'
>>> b = 'banana'
>>> a is b
True
如上所述,您不应该使用is
来确定字符串的相等性。但是,如果您需要使用is
,这可能会有帮助
请注意,
intern
函数以前是Python 2上的内置函数,但在Python 3中被移到了sys
模块。如果您不确定自己在做什么,请使用“==”。
如果你对它有更多的了解,你可以用“是”来表示已知的对象,比如“无”
否则,您最终会想知道为什么事情不起作用以及为什么会发生这种情况:
>>> a = 1
>>> b = 1
>>> b is a
True
>>> a = 6000
>>> b = 6000
>>> b is a
False
我甚至不确定是否有
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
>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False
>>> a = 'banana'
>>> b = 'banana'
>>> a is b
True
>>> 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 = [1, 2, 3]
>>> b = a
>>> b is a
True