【问题标题】:python total_ordering : why __lt__ and __eq__ instead of __le__?python total_ordering:为什么使用 __lt__ 和 __eq__ 而不是 __le__?
【发布时间】:2013-04-20 17:44:10
【问题描述】:

在 Python3 中,functools.total_ordering decorator 只允许重载 __lt____eq__ 以获取所有 6 个比较运算符。

我不明白为什么在一个就足够的情况下必须编写两个运算符,即__le____ge__,而所有其他运算符都会相应地定义:

a < b   <=>   not (b <= a)
a > b   <=>   not (a <= b)
a == b   <=>   (a <= b) and (b <= a)
a != b   <=>   (a <= b) xor (b <= a)

这仅仅是因为 xor 运算符本身不存在吗?

【问题讨论】:

  • xor 本身确实存在。
  • @MartijnPieters 只能按位异或,不是吗?
  • 按位异或是用于所有意图和目的的布尔异或,无论是在 Python 中还是在许多其他语言中。在 Python 中,boolintFalse == 0True == 1 的子类。所以True ^ False等等工作就好了。

标签: python python-3.x comparison-operators


【解决方案1】:

文档声明您必须定义__lt__()__le__()__gt__()__ge__()之一,但只有应该提供__eq__()方法。

换句话说,__eq__ 方法是可选的

total_ordering implementation 不需要您指定__eq__ 方法;它只测试__lt__()__le__()__gt__()__ge__() 方法。它提供了多达 3 种缺失的特殊方法,基于这 4 种方法之一。

您不能将订单基于只是 __le____ge__,因为您不能假设您可以交换 ab;如果b 是不同的类型,b.__le__ 可能无法实现,因此您的a &lt; b &lt;=&gt; not (b &lt;= a) 映射无法得到保证。如果未定义 __le__ 但已定义 __lt__,则实现使用 (a &lt;= b) and (a != b)

完整的映射表是:

comparison available alternative
a &gt; b a &lt; b (not a &lt; b) and (a != b)
a &lt;= b (not a &lt;= b)
a &gt;= b (a &gt;= b) and (a != b)
a &lt;= b a &lt; b (a &lt; b) or (a == b)
a &gt; b (not a &gt; b)
a &gt;= b (not a &gt;= b) or (a == b)
a &lt; b a &lt;= b (a &lt;= b) and (a != b)
a &gt; b (not a &gt; b) and (a != b)
a &gt;= b (not a &gt;= b)
a &gt;= b a &lt; b (not a &lt; b)
a &lt;= b (not a &lt;= b) or (a == b)
a &gt; b (a &gt; b) or (a == b)

__eq__ 方法是可选的,因为基础object 对象为您定义了一个;只有当它们是同一个对象时,两个实例才被认为是相等的; ob1 == ob2 仅当 ob1 is ob2True。见do_richcompare() function in object.c;请记住,代码中的== 运算符是比较指针。

【讨论】:

  • @mtraceur:我添加了一个动机:你不能依赖b 上的任何特殊方法,只有a 上的方法可以被依赖或生成。
  • 感谢 Martijn,我认为这涵盖/解释了我正在寻找的内容!我已相应地删除了我剩余的评论。
猜你喜欢
  • 1970-01-01
  • 2010-11-06
  • 2012-03-16
  • 2013-01-04
  • 2016-11-01
  • 2019-02-01
  • 1970-01-01
  • 2013-12-07
  • 2015-12-07
相关资源
最近更新 更多