==
和is
Python 之间有区别吗?
是的,它们有非常重要的区别。
==
:检查是否相等-语义是等效对象(不一定是同一对象)将被测试为相等。如文档所述:
运算符<,>,==,> =,<=和!=比较两个对象的值。
is
:检查身份-语义是对象(保存在内存中)是对象。再次,文档说:
运算符is
和is not
对象身份测试:x is y
当且仅当x
和y
是相同对象时,才为true 。使用该id()
功能确定对象身份。x is not y
产生反真值。
因此,对身份的检查与对对象ID的相等性检查相同。那是,
a is b
是相同的:
id(a) == id(b)
where id
是返回整数的内建函数,该整数“保证同时存在的对象之间是唯一的”(请参阅参考资料help(id)
),而where a
和b
则是任意对象。
其他使用说明
您应该将这些比较用于它们的语义。使用is
检查身份和==
检查平等。
因此,通常,我们使用is
来检查身份。当我们检查一个仅在内存中存在一次的对象(在文档中称为“单个”)时,这通常很有用。
用例is
包括:
None
- 枚举值(当使用枚举模块中的枚举时)
- 通常是模块
- 通常是由类定义产生的类对象
- 通常由函数定义产生的函数对象
- 在内存中应该只存在一次的所有其他内容(通常是所有单例)
- 您希望通过身份获得的特定对象
通常的用例==
包括:
- 数字,包括整数
- 弦
- 清单
- 套
- 词典
- 自定义可变对象
- 在大多数情况下,其他内置的不可变对象
一般使用情况下,再次对==
,就是你想可能不是对象相同的对象,相反,它可能是一个相当于一个
PEP 8方向
PEP 8,标准库的官方Python样式指南还提到了以下两个用例is
:
与单例之类的比较None
应始终使用is
或
is not
,而不应使用相等运算符。
另外,当心if x
您的意思if x is not None
,例如当测试是否将默认None
设置为的变量或参数设置为其他值时,请当心编写。另一个值可能具有在布尔上下文中可能为false的类型(例如容器)!
从身份推断平等
如果is
为true,通常可以推断出相等性-从逻辑上讲,如果对象是自身,则它应该测试为等同于自身。
在大多数情况下,此逻辑是正确的,但它依赖于__eq__
特殊方法的实现。正如文档所说,
相等比较(==
和!=
)的默认行为基于对象的标识。因此,具有相同身份的实例的相等比较会导致相等,而具有不同身份的实例的相等比较会导致不平等。这种默认行为的动机是希望所有对象都是自反的(即x为y意味着x == y)。
为了保持一致性,建议:
平等比较应该是自反的。换句话说,相同的对象应该比较相等:
x is y
暗示 x == y
我们可以看到这是自定义对象的默认行为:
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)
相反,通常也是如此-如果某项测试的结果不相等,则通常可以推断出它们不是同一对象。
由于可以对相等性测试进行自定义,因此该推论并不总是适用于所有类型。
一个例外
一个显着的例外是nan
-它总是被测试为不等于自身:
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False
检查身份比检查相等性要快得多(可能需要递归检查成员)。
但是它不能替代相等性,在相等性中您可能会发现多个对象相等。
请注意,比较列表和元组的相等性将假定对象的身份相同(因为这是一个快速检查)。如果逻辑不一致,这可能会产生矛盾-就是这样nan
:
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True
警示故事:
问题是试图is
用来比较整数。您不应该假定整数的实例与另一个引用获得的实例相同。这个故事解释了为什么。
一个注释者的代码依赖于以下事实:小整数(包括-5至256)在Python中是单例,而不是检查是否相等。
哇,这可能会导致一些隐患。我有一些检查a是否为b的代码,它可以按我的意愿工作,因为a和b通常很小。该错误仅在生产六个月后才出现在今天,因为a和b最终足够大而无法缓存。– gwg
它在开发中起作用。它可能已经通过了一些单元测试。
它可以在生产中使用-直到代码检查出大于256的整数为止,此时它在生产中失败了。
这是生产失败,可能已在代码审查中或可能通过样式检查器捕获。
让我强调一下:不要is
用于比较整数。
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foo
输出:False True False
。