Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么使用'==';或';是';有时会产生不同的结果?_Python_String_Comparison_Identity_Equality - Fatal编程技术网

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,则当且仅当对象是同一对象时,结

我有一个Python程序,其中两个变量被设置为值
“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