2010-09-05 139 views
10

我发现我可以使用==运算符来比较所有的原始数据类型(整数,字符串,布尔值,浮点数等),还列出,元组,组和包含原始数据类型的字典。在这些情况下,==操作员检查两个对象是否相等。但在另一些情况下(试图比较的,我创建类的实例)的==运营商只检查,如果两个变量引用同一对象(所以在这些情况下,==操作相当于is运营商)什么时候“==”运算符不等于“is”运算符? (蟒蛇)

我的问题是:==运营商什么时候不仅仅比较身份?

编辑:我使用Python 3

+1

本质上说,''==从'is',当一个类重写它从'object'继承'__eq__'方法不同,所以没有简单的答案,这个问题。根据您使用的Python版本,由于存在'__cmp__',事情会变得更加复杂。除了好奇之外,这个问题是否有实际的理由? – Dirk 2010-09-05 20:39:04

+0

@Dirk,谢谢。我主要是出于好奇,但我也认为知道什么时候可以使用==运算符来检查对象相等是很好的。 – snakile 2010-09-05 20:46:26

回答

19

在Python中,==运营商在magic method __eq__,在默认情况下通过身份比较实现它的条款执行。但是,您可以重写该方法以提供您自己的对象平等概念。请注意,如果您这样做,则通常还会覆盖至少__ne__(实现!=运算符)和__hash__,它们计算实例的哈希代码。

我发现它非常有用,甚至在Python,让我__eq__实现符合设定了在Java语言中equals方法,即实现规则:

  • 自反性:对于任何非空引用值x,x.equals(x)应该返回true。
  • 它是对称的:对于任何非空引用值x和y,x.equals(y)的应返回true当且仅当y.equals(x)返回真。
  • 传递性:对于任何非空引用值x,y和z,如果x.equals(y)的返回true并且y.equals(z)的返回true,那么x.equals(z)的应返回true 。
  • 它是一致的:对于任何非空引用值x和y,的x.equals(y)的多个调用始终返回true或始终返回假,没有设置中使用的信息等于在对象上比较被修改。
  • 对于任何非空引用值x,x.equals(null)应该返回false。

最后一个可能应该用None代替null,但是Python中的规则并不像Java那样容易。

+0

感谢您为规则设置'__eq__' – snakile 2010-09-05 21:18:48

+3

这个“规则”具有强大的数学根源:http://en.wikipedia.org/wiki/Equivalence_relation – 2010-09-06 06:16:30

+1

告诉javascript - > http://stackoverflow.com/questions/1995113/strangest-language-feature/1998224#1998224 – wim 2011-07-04 12:45:53

16

==is总是在概念上不同:前者代表左侧对象的__eq__ [1],后者总是检查身份,没有任何委托。什么似乎混淆你的是,object.__eq__(这会直接默认继承了用户编码类,不重写,当然!)在身份方面实现(毕竟,裸object具有绝对没有到检查,除了其身份,所以还有什么可能呢?! - )。

[1]为简单起见省略了__cmp__方法的遗留概念,这只是一个边际复杂因素,并且在该段落的要点中没有任何重要的改变;-)。

4

什么也许是最重要的一点是,建议是始终使用:

if myvalue is None: 

if myvalue == None: 

而且从来没有使用:

if myvalue is True: 

但使用:

if myvalue: 

这个稍后的一点对我来说并不是那么晚了,因为我认为有时候需要将布尔值True与其他真值(如“Alex Martelli”)分开,并说“Alex Martelli”中没有False(绝对不是,甚至不是引发异常:)),但是“Alex Martelli”中有“'(如同其他字符串)。

+0

如果'myvalue是None'比'if myvalue == None'更好的原因是什么? – snakile 2010-09-05 21:47:54

+3

有关规则,请参阅PEP8。看到亚历克斯关于__eq__的评论,另外它更快:http://jaredgrubb.blogspot.com/2009/04/python-is-none-vs-none.html – 2010-09-05 22:01:22

7

==不仅仅是在涉及整数时比较身份。它不仅检查两个整数是否是同一个对象;它实际上确保了它们的值匹配。试想一下:

>>> 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情况:

>>> del y 
>>> del x 
>>> x=1 
>>> y=1 
>>> x==y,x is y 
(True, True) 
+2

有趣。 +1 – snakile 2010-09-05 22:11:44