クラスMyClass
があり、これには2つのメンバー変数foo
とbar
が含まれています。
class MyClass:
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
このクラスのインスタンスは2つあり、それぞれfoo
とbar
の値が同じです。
x = MyClass('foo', 'bar')
y = MyClass('foo', 'bar')
ただし、それらを同等かどうか比較すると、PythonはFalse
を返します。
>>> x == y
False
どうすればpythonこれら2つのオブジェクトを等しいと見なすことができますか?
メソッドを実装する必要があります __eq__
:
class MyClass:
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
def __eq__(self, other):
if not isinstance(other, MyClass):
# don't attempt to compare against unrelated types
return NotImplemented
return self.foo == other.foo and self.bar == other.bar
次のように出力されます:
>>> x == y
True
__eq__
を実装すると、クラスのインスタンスが自動的にハッシュ不可になります。つまり、セットや辞書に格納することはできません。不変の型をモデル化していない場合(つまり、属性foo
およびbar
がオブジェクトの存続期間内に値を変更する可能性がある場合)は、インスタンスをハッシュ不可のままにすることをお勧めします。
不変型をモデル化する場合は、datamodelフック __hash__
も実装する必要があります。
class MyClass:
...
def __hash__(self):
# necessary for instances to behave sanely in dicts and sets.
return hash((self.foo, self.bar))
__dict__
をループして値を比較するというアイデアのような一般的な解決策はお勧めできません-__dict__
には比較できないまたはハッシュできないタイプが含まれている可能性があるため、真に一般的ではありません。
N.B .: Python 3の前に、__cmp__
の代わりに __eq__
を使用する必要があることに注意してください。 Python 2人のユーザーは、 __ne__
を実装することもできます。これは、不平等に対する適切なデフォルト動作(つまり、等式結果の反転)がPythonで自動的に作成されないためです2。
オブジェクトの リッチ比較演算子 をオーバーライドします。
class MyClass:
def __lt__(self, other):
# return comparison
def __le__(self, other):
# return comparison
def __eq__(self, other):
# return comparison
def __ne__(self, other):
# return comparison
def __gt__(self, other):
# return comparison
def __ge__(self, other):
# return comparison
このような:
def __eq__(self, other):
return self._id == other._id
クラスに__eq__
メソッドを実装します。このようなもの:
def __eq__(self, other):
return self.path == other.path and self.title == other.title
編集:オブジェクトに等しいインスタンスディクショナリがある場合にのみ、オブジェクトを同等に比較する場合:
def __eq__(self, other):
return self.__dict__ == other.__dict__
要約として:
__eq__
ではなく__cmp__
を実装することをお勧めします(2.1で__eq__
が追加されました)__ne__
も実装することを忘れないでください(非常に特殊な場合を除き、return not self.__eq__(other)
またはreturn not self == other
のようなものでなければなりません)Noneにできるオブジェクトと比較する場合は、実装する必要があります。インタプリタは推測できません...(以下の例を参照)
class B(object):
def __init__(self):
self.name = "toto"
def __eq__(self, other):
if other is None:
return False
return self.name == other.name
class A(object):
def __init__(self):
self.toto = "titi"
self.b_inst = B()
def __eq__(self, other):
if other is None:
return False
return (self.toto, self.b_inst) == (other.toto, other.b_inst)
属性ごとの比較を取得し、失敗するかどうか、どこで失敗するかを確認する場合は、次のリスト内包表記を使用できます。
[i for i,j in
Zip([getattr(committed_vans_events[0][0].request, attr)
for attr in dir(committed_vans_events[0][0].request)],
[getattr(self.vans_states[0].onboard_passengers[0], attr)
for attr in dir(self.vans_states[0].onboard_passengers[0])])
if not i==j]
ここでの追加の利点は、PyCharmでデバッグするときに1行圧縮して「式の評価」ウィンドウに入力できることです。