类型几乎影响对象行为的所有方面 . 甚至对象身份的重要性在某种意义上也会受到影响:对于不可变类型,操作 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 . 例如,在a = 1之后; b = 1,a和b可能会或可能不会引用具有值1的同一对象,具体取决于实现,但在c = []之后; d = [],c和d保证引用两个不同的,唯一的,新创建的空列表 . (注意c = d = []将同一个对象分配给c和d . )
15 回答
我正在回答这个问题,即使这个问题已经过时了,因为上述答案没有引用语言参考
实际上是运算符检查标识和==运算符检查是否相等,
From Language Reference:
类型几乎影响对象行为的所有方面 . 甚至对象身份的重要性在某种意义上也会受到影响:对于不可变类型,操作 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 . 例如,在a = 1之后; b = 1,a和b可能会或可能不会引用具有值1的同一对象,具体取决于实现,但在c = []之后; d = [],c和d保证引用两个不同的,唯一的,新创建的空列表 . (注意c = d = []将同一个对象分配给c和d . )
所以从上面的语句我们可以推断,当用“is”检查时,不可变类型的字符串可能会失败,并且当用“is”检查时可能检查成功
这同样适用于int,tuple,它们也是不可变类型
is
关键字是对象标识的测试,而==
是值比较 .如果使用
is
,则当且仅当对象是同一对象时,结果才为真 . 但是,只要对象的值相同,==
将为true .如果您不确定自己在做什么,请使用'==' . 如果您对此有更多的了解,可以使用'is'作为'None'等已知对象 .
否则你最终会想知道为什么事情不起作用以及为什么会这样:
我甚至不确定在不同的python版本/实现之间是否保证一些东西保持不变 .
这是一个旁注,但在惯用的python中,你经常会看到如下内容:
这是安全的,因为there is guaranteed to be one instance of the Null Object (i.e., None) .
is
将比较内存位置 . 它用于对象级比较 .==
将比较程序中的变量 . 它用于检查 Value 水平 .is
检查地址级别等效性==
检查 Value 水平等值is
是身份测试,==
是相等测试 . 您的代码中会发生什么,将在解释器中模拟如下:所以,难怪他们不一样,对吧?
换句话说:
is
是id(a) == id(b)
根据我对python的有限经验,
is
用于比较两个对象,看它们是否是同一个对象,而不是两个具有相同值的不同对象 .==
用于确定值是否相同 .这是一个很好的例子:
s1
是一个unicode字符串,s2
是一个普通字符串 . 它们的类型不同,但值相同 .我认为这与以下事实有关:当'is'比较评估为false时,使用两个不同的对象 . 如果它的计算结果为true,那意味着它在内部使用相同的精确对象而不是创建一个新对象,这可能是因为你在2秒左右的时间内创建了它们,并且因为它们之间没有很大的时间差,所以优化和使用相同的对象 .
这就是为什么你应该使用等于运算符
==
而不是is
来比较字符串对象的值 .在这个例子中,我创建了s2,它是一个先前等于'one'的不同字符串对象,但它与
s
不是同一个对象,因为解释器没有使用与我最初没有将它分配给'one'相同的对象,如果我有它会使它们成为同一个对象 .==
运算符测试值等价 .is
运算符测试对象标识,Python测试两者是否真的是同一个对象(即,存在于内存中的同一地址) .在此示例中,Python仅创建了一个字符串对象,并且
a
和b
都引用了它 . 原因是Python内部缓存并重用一些字符串作为优化,内存中只有一个字符串'banana',由a和b共享;要触发正常行为,您需要使用更长的字符串:创建两个列表时,您将获得两个对象:
在这种情况下,我们会说两个列表是等价的,因为它们具有相同的元素,但不相同,因为它们不是同一个对象 . 如果两个对象相同,它们也是等价的,但如果它们是等价的,则它们不一定相同 .
如果
a
引用了一个对象并且您指定了b = a
,则两个变量都引用同一个对象:is
是身份测试,==
是相等测试 . 这是什么意思是is
是一种检查两件事物是相同的东西,还是只是等价物的方法 .假设你有一个简单的
person
对象 . 如果它被命名为'Jack'并且是'23'岁,它相当于另一个23岁的杰克,但它不是同一个人 .他们的年龄相同,但他们不是同一个人 . 字符串可能与另一个字符串等效,但它不是同一个对象 .
而是尝试使用
上面的代码会给出
TRUE
的结果上面的代码会给出
TRUE
的结果上面的代码会给出结果
FALSE
最后要注意的是,您可以使用实习函数来确保您获得对同一字符串的引用:
如上所述,您可能不应该做的是确定字符串上的相等性 . 但这可能有助于了解您是否有某种奇怪的要求使用
is
.请注意,实习函数已从内置函数转移到Python 3的模块
sys
中 .is
是身份测试,==
是相等测试(参见Python Documentation) .在大多数情况下,如果
a is b
,则a == b
. 但也有例外,例如:因此,您只能使用
is
进行身份测试,而不能使用相等测试 .这里的其他答案是正确的:
is
用于身份比较,而==
用于相等比较 . 因为你关心的是相等(两个字符串应该包含相同的字符),在这种情况下is
运算符是完全错误的,你应该使用==
.is
交互式工作的原因是(大多数)字符串文字默认为interned . 来自维基百科:因此,当您在程序中有两个字符串文字(字面上键入您的程序源代码,用引号括起来)时,Python编译器会自动生成字符串,使它们都存储在同一个字符串中记忆位置 . (请注意,这并不总是发生,并且发生这种情况的规则非常复杂,因此请不要在 生产环境 代码中依赖此行为!)
由于在交互式会话中,两个字符串实际存储在同一个内存位置,因此它们具有相同的标识,因此
is
运算符按预期工作 . 但是如果你通过其他方法构造一个字符串(即使该字符串包含完全相同的字符),那么字符串可能相同,但它不是相同的字符串 - 也就是说,它具有不同的标识,因为它是存储在内存中的不同位置 .我相信这被称为“实习”字符串 . Python就是这样做的,Java也是如此,在优化模式下进行编译时也是如此 .
如果使用两个相同的字符串,而不是通过创建两个字符串对象来浪费内存,则所有具有相同内容的实习字符串都指向相同的内存 .
这导致Python“is”运算符返回True,因为具有相同内容的两个字符串指向同一个字符串对象 . 这也将发生在Java和C中 .
这仅对节省内存有用 . 您不能依赖它来测试字符串相等性,因为各种解释器和编译器以及JIT引擎不能总是这样做 .