64

次のコード

class point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def dispc(self):
        return ('(' + str(self.x) + ',' + str(self.y) + ')')

    def __cmp__(self, other):
        return ((self.x > other.x) and (self.y > other.y))

Python 2では正常に動作しますが、Python3ではエラーが発生します。

>>> p=point(2,3)
>>> q=point(3,4)
>>> p>q
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: point() > point()

とに対してのみ機能し==ます!=

4

3 に答える 3

87

__lt__Python 3で順序付けするための豊富な比較メソッド、、、、、、、、を提供する必要が __gt__あります。参照:PEP207-豊富な比較__le____ge____eq____ne__

__cmp__使用されなくなりました。


より具体的には、とを引数として__lt__取り、がより小さいかどうかを返す必要があります。例えば:selfotherselfother

class Point(object):
    ...
    def __lt__(self, other):
        return ((self.x < other.x) and (self.y < other.y))

(これは賢明な比較実装ではありませんが、何を目指しているのかを判断するのは困難です。)

したがって、次の状況がある場合:

p1 = Point(1, 2)
p2 = Point(3, 4)

p1 < p2

これは次と同等になります。

p1.__lt__(p2)

を返しTrueます。

__eq__Trueポイントが等しい場合は戻りFalseます。他の方法も同様に機能します。


デコレータを使用する場合は、 andメソッドなどfunctools.total_orderingを実装するだけで済みます。__lt____eq__

from functools import total_ordering

@total_ordering
class Point(object):
    def __lt__(self, other):
        ...

    def __eq__(self, other):
        ...
于 2011-11-26T07:41:21.893 に答える
15

これはPython3の主要で意図的な変更でした。詳細については、ここを参照してください。

  • 順序比較演算子(<、、、、)は<=、オペランドに意味のある自然順序がない場合に例外を発生させます。したがって、、またはのような式は無効になり、たとえば、を返す代わりにraiseします。当然の結果として、異種リストの並べ替えはもはや意味がありません。すべての要素が互いに比較可能でなければなりません。これはと演算子には適用されないことに注意してください。異なるタイプの比較できないオブジェクトは、常に互いに等しくないように比較されます。>=>TypeError1 < ''0 > Nonelen <= lenNone < NoneTypeErrorFalse==!=
  • builtin.sorted()比較関数を提供する引数を受け入れlist.sort()なくなりました。代わりcmpに引数を使用してください。key注意keyreverse引数は「キーワードのみ」になりました。
  • cmp()関数はなくなったものとして扱われる必要があり、特別__cmp__()なメソッドはサポートされなくなりました。__lt__()必要に応じて、ソート、__eq__()with __hash__()、およびその他の豊富な比較に使用します。(本当に機能が必要な場合は、式をに相当するものとしてcmp()使用できます。)(a > b) - (a < b)cmp(a, b)
于 2011-11-26T07:36:23.063 に答える
9

Python3では、6つの豊富な比較演算子

__lt__(self, other) 
__le__(self, other) 
__eq__(self, other) 
__ne__(self, other) 
__gt__(self, other) 
__ge__(self, other) 

個別に提供する必要があります。これは、を使用して省略できますfunctools.total_ordering

ただし、これはほとんどの場合、かなり読みにくく、実用的ではないことがわかります。それでも、同様のコードを2つの関数に入れる必要があります。または、さらにヘルパー関数を使用する必要があります。

そのため、ほとんどの場合、PY3__cmp__以下に示すミックスインクラスを使用することを好みます。これにより、単一の__cmp__メソッドフレームワークが再確立されます。これは、ほとんどの場合、非常に明確で実用的でした。選択した豊富な比較をオーバーライドすることもできます。

あなたの例は次のようになります:

 class point(PY3__cmp__):
      ... 
      # unchanged code

PY3__cmp__ミックスインクラス:

PY3 = sys.version_info[0] >= 3
if PY3:
    def cmp(a, b):
        return (a > b) - (a < b)
    # mixin class for Python3 supporting __cmp__
    class PY3__cmp__:   
        def __eq__(self, other):
            return self.__cmp__(other) == 0
        def __ne__(self, other):
            return self.__cmp__(other) != 0
        def __gt__(self, other):
            return self.__cmp__(other) > 0
        def __lt__(self, other):
            return self.__cmp__(other) < 0
        def __ge__(self, other):
            return self.__cmp__(other) >= 0
        def __le__(self, other):
            return self.__cmp__(other) <= 0
else:
    class PY3__cmp__:
        pass
于 2016-08-26T12:28:22.717 に答える