web-dev-qa-db-ja.com

Python3.0でcmpパラメータがsort / sortedから削除されるのはなぜですか?

から python wikiIn Py3.0, the cmp parameter was removed entirely (as part of a larger effort to simplify and unify the language, eliminating the conflict between rich comparisons and the __cmp__ methods).

Cmpがpy3.0で削除された理由がわかりません

この例を考えてみましょう:

>>> def numeric_compare(x, y):
        return x - y
>>> sorted([5, 2, 4, 1, 3], cmp=numeric_compare)
[1, 2, 3, 4, 5]

そして、このバージョンを検討してください(3.0と推奨および互換性があります):

def cmp_to_key(mycmp):
    'Convert a cmp= function into a key= function'
    class K(object):
        def __init__(self, obj, *args):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
        def __gt__(self, other):
            return mycmp(self.obj, other.obj) > 0
        def __eq__(self, other):
            return mycmp(self.obj, other.obj) == 0
        def __le__(self, other):
            return mycmp(self.obj, other.obj) <= 0
        def __ge__(self, other):
            return mycmp(self.obj, other.obj) >= 0
        def __ne__(self, other):
            return mycmp(self.obj, other.obj) != 0
    return K

>>> sorted([5, 2, 4, 1, 3], key=cmp_to_key(reverse_numeric))
[5, 4, 3, 2, 1]

後者は非常に冗長であり、前者でも1行だけで同じ目的を達成できます。別のメモでは、__cmp__メソッドを作成するカスタムクラスを作成しています。私のウェブ全体での小さな読みから、__lt__,__gt__,__eq__,__le__,__ge__,__ne__ and not __cmp__を書くことをお勧めします。ここでも、なぜこの推奨事項ですか? __cmp__を単純に定義して、生活をシンプルにすることはできませんか?

37
brain storm

2つのオブジェクトaおよびbの場合、__cmp__には、a < ba == b、およびa > bはtrueです。しかし、そうではない可能性があります。セットを検討してください。それらのどれも真ではないことが一般的です{1, 2, 3}{4, 5, 6}

__lt__と友達が紹介されました。しかし、その左Pythonとんでもない2つの順序付けメカニズムがあるため、柔軟性が低い方がPython 3.で削除されました。

6つの比較メソッドすべてを実際に実装する必要はありません。 @total_orderingデコレータ を使用して、__lt____eq__のみを実装できます。

編集:また、並べ替えの場合、key関数はcmpよりも効率的である可能性があることに注意してください。指定した例では、Python Python比較関数をO(n²)回呼び出します。ただし、key関数はO(n)回だけ呼び出す必要があります。戻り値が組み込み型である場合(非常によくあることです)、O(n²)のペアごとの比較はCを通過します。

25
Eevee

cmpは削除されました。これは、ほとんどの場合、.sort()およびsorted()key属性が優れているためです。それは何よりもCからの引き継ぎであり、起動が混乱していました。豊富な比較演算子(___cmp___、___lt___など)に個別の___gt___メソッドnextを実装する必要があったので、混乱し、役に立ちませんでした。

いつでも functools.cmp_to_key() を使用して、既存のcmp関数を調整できます。

あなたの特定の例は実装されているかもしれませんなしkey関数、もちろん、整数はすでに注文可能です; _reverse=True_を追加するだけです。

カスタムクラスの場合、 _@functools.total_ordering_デコレータ を使用して___eq___およびone比較演算子メソッド(___lt___、または___gt___など)を完全な順序付けの実装にします。

14
Martijn Pieters