誰かが私に2つの違いを説明できますか?それらは通常同等ですか?ここでは完全に間違っているかもしれませんが、各比較演算子は必然的に1つの「豊富な比較」メソッドに関連していると思いました。これはドキュメントからです:
演算子記号とメソッド名の対応は次のとおりです。
x<y
はx.__lt__(y)
を呼び出し、x<=y
はx.__le__(y)
を呼び出し、x==y
はx.__eq__(y)
を呼び出し、x!=y
はx.__ne__(y)
を呼び出し、x>y
はx.__gt__(y)
を呼び出し、x>=y
はx.__ge__(y)
を呼び出します。
これが私の混乱を示す例です。
Python 3.x:
dict1 = {1:1}
dict2 = {2:2}
>>> dict1 < dict2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'dict' and 'dict'
>>> dict1.__lt__(dict2)
NotImplemented
Python 2.x:
dict1 = {1:1}
dict2 = {2:2}
>>> dict1 < dict2
True
>>> dict1.__lt__(dict2)
NotImplemented
python 3の例から、dict1 < dict2
の呼び出しはサポートされていないようですが、Python 2の例はどうですか?なぜ受け入れられるのですか?
Python 2、in Python 3では、すべてのオブジェクトが比較演算子をサポートしているわけではありません。しかし、驚いたことに、どちらのバージョンも__lt__()
を呼び出すとNotImplemented
シングルトンを返します。 。
これは、___cmp__
_マジックメソッドに依存しています。これは、リッチ比較演算子が置き換えることを意図したものです。
_>>> dict1 = {1:1}
>>> dict2 = {2:2}
>>> dict1.__cmp__
<method-wrapper '__cmp__' of dict object at 0x10f075398>
>>> dict1.__cmp__(dict2)
-1
_
順序logicに関しては、ここにPython 2.7 ドキュメント :
マッピング(dictのインスタンス)は、(キー、値)のペアが等しい場合にのみ、等しいと比較されます。キーと値の同等性の比較により、再帰性が強化されます。
平等以外の結果は一貫して解決されますが、それ以外の定義はありません。
脚注付き:
以前のバージョンのPythonは、並べ替えられた(キー、値)リストの辞書式比較を使用していましたが、同等性を比較する一般的なケースでは非常にコストがかかりました。さらに以前のバージョンのPythonは、辞書をIDのみで比較しましたが、{}と比較することで辞書の空をテストできると期待されていたため、これは驚きをもたらしました。
また、Python 3.0では、順序が簡略化されています。これは ドキュメント からのものです。
順序比較演算子_
(<, <=, >=, >)
_は、オペランドに意味のある自然順序がない場合にTypeError例外を発生させます。
builtin.sorted()
およびlist.sort()
は、比較関数を提供するcmp引数を受け入れなくなりました。代わりにkey引数を使用してください。
cmp()
関数はなくなったものとして扱われる必要があり、__cmp__()
特殊メソッドはサポートされなくなりました。ソートには__lt__()
を使用し、__eq__()
と__hash__()
を使用し、必要に応じてその他の豊富な比較を行います。 (本当にcmp()
機能が必要な場合は、式_(a > b) - (a <> b)
_をcmp(a, b)
と同等のものとして使用できます。)
したがって、明示的に言うと、Python 2では、豊富な比較演算子が実装されていないため、dict
オブジェクトはデータから___cmp__
_にフォールバックします-モデル ドキュメント :
object.__cmp__(self, other)
リッチ比較(上記を参照)が定義されていない場合、比較操作によって呼び出されます。 self <otherの場合は負の整数、self == otherの場合はゼロ、self> otherの場合は正の整数を返す必要があります。
演算子に関する注意<
対 __lt__
:
import types
class A:
def __lt__(self, other): return True
def new_lt(self, other): return False
a = A()
print(a < a, a.__lt__(a)) # True True
a.__lt__ = types.MethodType(new_lt, a)
print(a < a, a.__lt__(a)) # True False
A.__lt__ = types.MethodType(new_lt, A)
print(a < a, a.__lt__(a)) # False False
<
呼び出し__lt__
クラスで定義されています。 __lt__
呼び出し__lt__
オブジェクトで定義されています。
それは通常同じです:)そしてそれを使うのは完全においしいです:A.__lt__ = new_lt