When is the `==` operator not equivalent to the `is` operator? (Python)
我注意到我可以使用==运算符来比较所有本机数据类型(整数,字符串,布尔值,浮点数等)以及包含本机数据类型的列表,元组,集合和字典。 在这些情况下,==运算符检查两个对象是否相等。 但在其他一些情况下(尝试比较我创建的类的实例),==运算符只检查两个变量是否引用相同的对象(因此在这些情况下,==运算符等效于is运算符)
我的问题是:==运算符什么时候做的不仅仅是比较身份?
编辑:我正在使用Python 3
-
本质上,==与is不同,只要一个类重写它继承自object的__eq__方法,所以对这个问题没有简单的答案。 根据您使用的Python版本,由于__cmp__的存在,事情变得更加复杂。 除了好奇心,这个问题还有一个实际的原因吗?
-
@Dirk,谢谢。 我主要是出于好奇而问这个问题,但我也觉得知道我何时可以使用==运算符检查对象相等性是件好事。
在Python中,==运算符是根据魔术方法__eq__实现的,默认情况下,它通过身份比较来实现。但是,您可以覆盖该方法,以提供您自己的对象相等概念。请注意,如果这样做,通常还会覆盖至少__ne__(实现!=运算符)和__hash__,它会计算实例的哈希码。
我发现,即使在Python中,我的__eq__实现也符合Java语言中为equals方法的实现规定的规则,即:
-
它是自反的:对于任何非空引用值x,x.equals(x)应该返回true。
-
它是对称的:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。
-
它是传递性的:对于任何非空引用值x,y和z,如果x.equals(y)返回true而y.equals(z)返回true,则x.equals(z)应返回true。
-
它是一致的:对于任何非空引用值x和y,x.equals(y)的多次调用始终返回true或始终返回false,前提是不修改在对象的equals比较中使用的信息。
-
对于任何非空引用值x,x.equals(null)应返回false。
最后一个应该用None替换null,但是Python中的规则并不像在Java中那么容易。
-
感谢您实施'eq'的规则集
-
这个"规则"具有很强的数学根源:en.wikipedia.org/wiki/Equivalence_relation
-
告诉javascript - > stackoverflow.com/questions/1995113/strangest-language-feature/
-
我想补充一点,python中的_eq_与Java有明显不同的行为,允许_eq_引发NotImplemented,这会将检查的相等性推迟到另一个类。这篇博文非常有用:jcalderone.livejournal.com/32837.html。这使您即使在处理继承时也能满足对称要求。如果Java允许这个功能,我相信Numbers类可以通过允许子类确定相等来实现Comparable。
-
请注意,在实现__eq__时不必实现__ne__魔术方法:默认情况下,a != b的测试将返回not (a == b)。
==和is总是在概念上是不同的:前者委托给左手对象的__eq__ [1],后者总是检查身份,没有任何委托。让你感到困惑的是object.__eq__(默认情况下由用户编码的类继承,当然不会覆盖它!)是以身份的形式实现的(毕竟,裸object绝对是没有什么可以检查,除了它的身份,所以还有什么可能呢?! - )。
[1]省略了__cmp__方法的遗留概念,这只是一个边缘的复杂因素,并且在段落的要点中没有任何重要的改变;-)。
当涉及整数时,==不仅仅比较身份。它不只是检查两个整数是否是同一个对象;它实际上确保了它们的值匹配。考虑:
1 2 3 4 5 6 7 8 9 10
| >>> x=10000
>>> y=10000
>>> x==y,x is y
(True, False)
>>> del x
>>> del y
>>> x=10000
>>> y=x
>>> x==y,x is y
(True, True) |
"标准"Python实现在幕后为小内容做了一些事情,因此在使用小值进行测试时,您可能会得到不同的东西。将此与等效的10000案例进行比较:
1 2 3 4 5 6
| >>> del y
>>> del x
>>> x=1
>>> y=1
>>> x==y,x is y
(True, True) |
可能最重要的一点是建议总是使用:
不
永远不要使用:
但使用:
对于我来说,后来的这一点并不是那么明确,因为我认为有时候将布尔值True与其他True值分开,比如"Alex Martelli",说"Alex Martelli"中没有False(绝对没有,它甚至引发了异常: ))但是"Alex Martelli"中有一个"(就像在任何其他字符串中一样)。
-
是什么让'如果myvalue为None'比'if myvalue == None'更好?
-
有关规则,请参阅PEP8。请参阅Alex关于eq的评论,另外它更快:jaredgrubb.blogspot.com/2009/04/python-is-none-vs-none.html