为什么要做出这个决定,只有原始作者知道,但是从手动得出的这些提示可以推断出原因:
数学上,binary relation≤是二元关系union,而二元关系≥是二元关系>和=的并集。那么,为什么有一个原因使得Python默认不以__le__
和__lt__
来实现__eq__
,而没有以__ge__
和__gt__
的方式实现__eq__
?
默认的实现可能是这样的(但可能是出于C的考虑,例如__ne__
:]
def __le__(self, other): result_1 = self.__lt__(other) result_2 = self.__eq__(other) if result_1 is not NotImplemented and result_2 is not NotImplemented: return result_1 or result_2 return NotImplemented def __ge__(self, other): result_1 = self.__gt__(other) result_2 = self.__eq__(other) if result_1 is not NotImplemented and result_2 is not NotImplemented: return result_1 or result_2 return NotImplemented
这将使用户不必始终实现这两种方法。
这里是Python documentation(强调我的部分)中的相关段落:
-以下关系始终有效,因此默认情况下在Python中实现(联合关系除外,这似乎是任意的,这是本文的原因):默认情况下,
__ne__()
委托给__eq__()
并求反除非是NotImplemented
。没有其他暗示比较运算符之间的关系,例如,真相(x<y or x==y)
的值并不表示x<=y
。Note。
以下关系仅对total orders有效,因此默认情况下在Python中未实现(但是,当它们由Python标准库提供的functools.total_ordering
类修饰器有效时,用户可以方便地实现它们:]]
functools.total_ordering
关系:“ 和≤是彼此的互补”。*反向关系通过complementary在Python中实现。
数学上,二元关系≤是二元关系和=的并集。因此,Python这样做有原因吗?
为什么要做出这个决定,只有原始作者知道,但是从手动得出的这些提示可以推断出原因:
要从单个root操作自动生成排序操作,请参见
NotImplemented
protocol。>>尽管此装饰器使创建行为良好的完全有序类型变得容易,但它[[does
NotImplemented
中的functools.total_ordering()
导出实际上是免费的,它只是functools.total_ordering()
的运算,即反转布尔值。
__ne__
和__eq__
的并集得出not o.__eq__(other)
意味着需要调用这两种方法,如果比较足够复杂,则可能会严重影响性能,特别是与优化的__le__
单一实现。
__lt__
装饰器显式地选择这种性能优于性能,但不会对您造成隐式影响。[如果您尝试执行未实现的比较,而不是未实现的隐式派生比较,并且可能会创建细微的错误,这也可能会引起显式错误,这取决于您对自定义类所做的操作。 Python在这里不会为您做任何猜测,而是由您自己决定是显式实现所需的比较,还是再次显式选择加入派生的比较。
TLDR:比较运算符不需要返回__eq__
。这意味着结果可能不会严格遵守“__le__
is total_ordering
”或类似关系。最重要的是,布尔值bool
可能无法保留其语义。
a <= b
。 (此示例还将a < b or a == b
等视为比or
更多。)一个例子是通过比较运算符表达时间点。例如,automatic __bool__
is not generally applicable仿真框架(免责声明:我维护此程序包)定义了__bool__
。我们可以使用比较来描述某个时间点“或之后”:
<=
在2000年之后。bool
at 2000。
usim
在2000年或之后。time > 2000
同样适用,但该限制更难解释。)time == 2000
)和何时将满足
time >= 2000
)。显然可以针对每种情况评估第一个。但是,第二个不能。等待<
和==
可以通过等待/睡眠直到确切的时间点来完成。但是,等待bool(time >= 2000)
需要等待时间点await (time >= 2000)
。后者无法准确表示,因为对于当代数类型,没有通用的无限小但非零的数。因此,==
和>=
的结果基本上与>
不同。将plus some infinitely small delay导出为“ ==
”将是错误的。因此,为了避免错误,>=
定义了>
和>=
,但没有定义> or ==
。自动定义比较运算符会避免这种情况,或者错误定义运算符。
为什么要做出这个决定,只有原始作者知道,但是从手动得出的这些提示可以推断出原因:
一个例子是通过比较运算符表达时间点。例如,automatic __bool__
is not generally applicable仿真框架(免责声明:我维护此程序包)定义了__bool__
。我们可以使用比较来描述某个时间点“或之后”:
<=
在2000年之后。bool
at 2000。