【问题标题】:When is the `==` operator not equivalent to the `is` operator? (Python)`==` 运算符何时不等同于 `is` 运算符? (Python)
【发布时间】:2010-09-05 20:32:21
【问题描述】:

我注意到我可以使用== 运算符来比较所有本机数据类型(整数、字符串、布尔值、浮点数等)以及包含本机数据类型的列表、元组、集合和字典。在这些情况下,== 运算符会检查两个对象是否相等。但在其他一些情况下(试图比较我创建的类的实例)== 运算符只检查两个变量是否引用同一个对象(因此在这些情况下== 运算符等效于is 运算符)

我的问题是:== 运算符何时不仅仅只是比较身份?

编辑:我正在使用 Python 3

【问题讨论】:

  • 本质上,==is 不同,每当一个类重写它从object 继承的__eq__ 方法时,所以这个问题没有简单的答案。根据您使用的 Python 版本,由于__cmp__ 的存在,事情变得更加复杂。除了好奇之外,这个问题还有实际原因吗?
  • @Dirk,谢谢。我问它主要是出于好奇,但我也认为知道什么时候可以使用 == 运算符来检查对象是否相等是件好事。

标签: python comparison equality


【解决方案1】:

在 Python 中,== 运算符是根据 magic method __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
  • 我要补充一点,python 中的 _eq_ 与 Java 有明显不同的行为,它允许 _eq_ 引发 NotImplemented,从而推迟检查与其他阶级平等。这篇博文很有帮助:jcalderone.livejournal.com/32837.html。即使在处理继承时,这也允许您满足对称要求。如果 Java 允许这个特性,我相信 Numbers 类可以通过允许子类确定相等性来实现 Comparable。
  • 请注意,当您实现__eq__ 时,您不必必须实现__ne__ 魔术方法:默认情况下,测试a != b 将返回not (a == b)
【解决方案2】:

==is 在概念上总是不同的:前者代表左侧对象的__eq__ [1],后者总是检查身份,没有任何委托。似乎让您感到困惑的是object.__eq__(当然,默认情况下,它被不覆盖它的用户编码类继承!)是根据身份实现的(毕竟,一个裸露的object 绝对没有可以检查除了它的身份,那么它还能做什么呢?!-)。

[1] 为简单起见,省略了 __cmp__ 方法的遗留概念,这只是一个边缘的复杂性,不会改变段落主旨中的任何重要内容;-)。

【讨论】:

    【解决方案3】:

    当涉及整数时,== 不仅仅是比较身份。它不只是检查两个整数是否是同一个对象;它实际上确保它们的值匹配。考虑:

    >>> 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)
    

    【讨论】:

      【解决方案4】:

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

      if myvalue is None:
      

      不是

      if myvalue == None:
      

      永远不要使用:

      if myvalue is True:
      

      但使用:

      if myvalue:
      

      后一点对我来说不是那么清楚,因为我认为有时将布尔 True 与 "Alex Martelli" 等其他 True 值分开,说 "Alex Martelli" 中没有 False (绝对不是,它甚至引发异常 :) )但“Alex Martelli”中有 '' (与任何其他字符串一样)。

      【讨论】:

      猜你喜欢
      • 2012-09-03
      • 2012-04-07
      • 1970-01-01
      • 1970-01-01
      • 2011-05-04
      • 2016-07-29
      • 2014-03-22
      • 2012-06-19
      • 1970-01-01
      相关资源
      最近更新 更多