[解決済み] cmp__の代わりに__lt__を使用する。
質問
Python 2.xでは比較演算子をオーバーロードする方法が2つあります。
__cmp__
または、次のようなリッチな比較演算子です。
__lt__
.
リッチ比較のオーバーロードが好ましいと言われていますが、なぜでしょうか?
リッチ比較演算子は、それぞれを実装するのは簡単ですが、ほぼ同じロジックでいくつも実装しなければなりません。 しかし、もしビルトインの
cmp
とタプルオーダーがあれば
__cmp__
は非常にシンプルになり、すべての比較を満たすようになります。
class A(object):
def __init__(self, name, age, other):
self.name = name
self.age = age
self.other = other
def __cmp__(self, other):
assert isinstance(other, A) # assumption for this example
return cmp((self.name, self.age, self.other),
(other.name, other.age, other.other))
このシンプルさは、リッチな比較の6つすべて(!)をオーバーロードするよりもずっと私のニーズを満たしているように思えます。 (ただし、"swapped argument"/reflected 動作に依存する場合、それを 4 つに減らすことができますが、私の謙虚な意見では、それは複雑さの純増という結果になります)。
をオーバーロードするだけなら、私が注意しなければならない予期せぬ落とし穴はありますか?
__cmp__
?
を理解しています。
<
,
<=
,
==
などの演算子は、他の目的のためにオーバーロードすることができ、好きなオブジェクトを返すことができます。 私はそのアプローチの利点について尋ねているのではなく、これらの演算子を数値のために意味するのと同じ意味で比較のために使用する場合の違いについてだけ尋ねています。
更新しました。
クリストファーとして
が指摘したように
,
cmp
が 3.x では消えている。
のように簡単に比較の実装ができる代替手段はないのでしょうか?
__cmp__
?
どのように解決するのですか?
そうですね、すべてを実装するのは簡単で、例えば
__lt__
をミキシンクラス(またはメタクラス、またはクラスデコレーター)で実装するのは簡単です。
例えば
class ComparableMixin:
def __eq__(self, other):
return not self<other and not other<self
def __ne__(self, other):
return self<other or other<self
def __gt__(self, other):
return other<self
def __ge__(self, other):
return not self<other
def __le__(self, other):
return not other<self
これで、あなたのクラスでは
__lt__
を定義し、ComparableMixin を多重継承することができます(もしあれば、他のベースが必要な後に)。クラス デコレーターは非常に似ていて、装飾する新しいクラスの属性として同様の関数を挿入するだけです (その結果、実行時に微視的に速くなり、メモリの点では同様に微小なコストとなるかもしれません)。
もちろん、もしあなたのクラスが(例えば)
__eq__
と
__ne__
を定義する場合、ミキシンのバージョンを使用しないように直接定義する必要があります(たとえば
dict
のように) -- 実際には
__ne__
として、それを容易にするために定義されるかもしれません。
def __ne__(self, other):
return not self == other
のみで構成されていますが、上のコードでは、対称性を保つために
<
;-).
なぜ
__cmp__
は行かなければならなかったのかというと、私たちは
した
ある
__lt__
といった具合に、まったく同じことをするのになぜ別の別の方法を持ち続けるのでしょうか? すべてのPythonランタイム(Classic, Jython, IronPython, PyPy, ...)において、これはとてもデッドウェイトなのです。 そのコードは
は間違いなく
C言語ではISO標準の"Spirit of C"のセクションで同じ原則を掲げています)。
これは、私たちがわざわざ禁止していることを意味するものではありませんが (たとえば、いくつかの用途における mixin とクラス装飾の間のほぼ等価性)、それは間違いなく を行います。 というのは、まったく同じタスクを実行するために複数の同等のアプローチをサポートするために、コンパイラやランタイムに冗長に存在するコードを持ち歩くことは好ましくないからです。
さらなる編集:多くのクラスに対して比較とハッシュを提供するさらに良い方法が実際に存在し、質問の中のそれを含みます。
__key__
メソッドです。私はそのためのPEPを書くことができなかったので、あなたがそれを好きなら、現在ミキシン(&c)でそれを実装する必要があります。
class KeyedMixin:
def __lt__(self, other):
return self.__key__() < other.__key__()
# and so on for other comparators, as above, plus:
def __hash__(self):
return hash(self.__key__())
インスタンスの他のインスタンスとの比較は、いくつかのフィールドを持つそれぞれのタプルを比較することに集約されるのが非常に一般的なケースです -- そして、ハッシュもまったく同じ基盤で実装されるべきです。その
__key__
は、そのニーズに直接応える特別な方法です。
関連
-
[解決済み] なぜlist.join(string)ではなくstring.join(list)なのでしょうか?
-
[解決済み] Matplotlibでプロットを表示するのではなく、画像ファイルに保存する。
-
[解決済み] なぜdict[key]ではなく、dict.get(key)なのか?
-
[解決済み] NotImplementedErrorを発生させずにNotImplementedを返す理由
-
[解決済み] googletransがエラー 'NoneType' オブジェクトに 'group' 属性がない、と言って動かなくなった。
-
[解決済み] 辞書のキーと値を交換するにはどうすればよいですか?
-
[解決済み] DataFrameに日付間の日数カラムを追加する pandas
-
[解決済み] Ctrl-CでPythonスクリプトを終了できない
-
[解決済み] tensorflowのCPUのみのインストールでダイナミックライブラリ 'cudart64_101.dll' を読み込めなかった
-
[解決済み] if 節の終了方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] mixinとは何か、なぜ有用なのか?
-
[解決済み] DataFrameの文字列、dtypeがobjectの場合
-
[解決済み] PythonでのAWS Lambdaのインポートモジュールエラー
-
[解決済み] dict を txt ファイルに書き、それを読み取る?
-
[解決済み] 小数点以下1桁を取得する[重複]。
-
[解決済み] Django Rest Framework ファイルアップロード
-
[解決済み] Jupyter (IPython)ノートブックのセッションをpickleして保存する方法
-
[解決済み] 異なる順序で同じ要素を持つ2つのJSONオブジェクトを等しく比較するには?
-
[解決済み] PyQtアプリケーションのスレッド化。QtスレッドとPythonスレッドのどちらを使うか?
-
[解決済み] Pythonのユーザー定義クラスをソート、ハッシュ可能なものにする