少し気の利かない仕様のような気がします。
これをフォローしてくれるのが functools の total_ordering です。
total_ordering はデコレータで、__lt__()、__le__()、__gt__()、__ge__() の4つの不等式系関数のうち最低1つと __eq__() を持っているクラスを修飾し、全6つの不等号・等号演算子に対応するようになります。
@total_ordering # デコレータ
class Stored(object):
def __init__(self, value):
self.value = value
def __lt__(self, rhs):
return self.value < rhs.value
def __eq__(self, rhs):
return self.value == rhs.value
# 全6つの不等号・等号に対応
>>> Stored(1) < Stored(2)
True
>>> Stored(1) <= Stored(2)
True
>>> Stored(1) > Stored(2)
False
>>> Stored(1) >= Stored(2)
False
>>> Stored(1) == Stored(2)
False
>>> Stored(1) != Stored(2)
True
__le__() や __ge__() が定義されていなくても、<= や >= が呼ばれています。と、一見便利そうな total_ordering ですが、実際にはあまり使う機会がありません。
第一の理由は、わざわざ total_ordering で修飾するのが煩わしい、ためです。__lt__() を定義した時点で < とそのフォールバックの > に対応でき、さらに __eq__() を定義することで == とそのフォールバックの != に対応できます。つまり、total_ordering の前提条件の時点で6つの不等号・等号のうち、4つはカバーできることになります。なので、total_ordering を使うよりも、あと1つ __le__() あたりを定義してした方が手っ取り早い、というわけです。
もう一つの理由は、total_ordering を使うと動作が遅くなる、ためです。不等式は数学的クラスでよく使われますが、数学的クラスでは動作速度が重要となります。そのような使用目的では、total_ordering を使うよりも、愚直に全6つの不等式・等式系関数を定義した方が、動作は速くなります。
0 件のコメント:
コメントを投稿