概要
Pythonでインスタンスを比較するとき、__eq__メソッドを使いたいことがある。
独自の方法で複数のインスタンスが同じか確認したいためだ。
ただ、この**__eq__メソッドをオーバーライドした時は、同時に__hash__**メソッドについても考える必要がある。
__eq__をオーバーライドすると、デフォルトでは__hash__がNoneを返すためだ。
もし、__eq__メソッドをオーバーライドしたオブジェクトをディクショナリのキーやセットで使うときなど(※)は**__hash__**メソッドもオーバーライドする。
※ハッシュ可能オブジェクトの場合
__eq__メソッドをオーバーライドしない場合
example_not_override.py
class TestNotEq:
def __init__(self):
self.a = "a"
test_not_eq_1 = TestNotEq()
test_not_eq_2 = TestNotEq()
test_not_eq_1 == test_not_eq_2
Out: False
test_not_eq_1.__hash__()
Out: -9223371891910350837
test_not_eq_2.__hash__()
Out: -9223371891910350809
この場合、self.a
に同じ値が入っているインスタンスtest_not_eq_1
とtest_not_eq_2
は==
で比較するとFalse
となる。
__eq__メソッドをオーバーライドした場合
example_override.py
class TestEq:
def __init__(self):
self.a = "a"
def __eq__(self, other):
return self.a == other.a
test_eq_1 = TestEq()
test_eq_2 = TestEq()
test_eq_1 == test_eq_2
Out: True
test_eq_1.__hash__()
Traceback (most recent call last):
File "C:\Python\Python37\lib\site-packages\IPython\core\interactiveshell.py", line 3326, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-7-10d68bdb2b74>", line 1, in <module>
test_eq_1.__hash__()
TypeError: 'NoneType' object is not callable
==
での比較結果はTrue
となるが、__hash__
メソッドの呼び出しは失敗する。
これは__hash__
がNone
になっているためである。
test_eq_1.__hash__ == None
Out: True
対応 >>> __hash__メソッドをオーバーライドする
example_override_hash.py
class TestEq:
def __init__(self):
self.a = "a"
def __eq__(self, other):
return self.a == other.a
def __hash__(self):
return super().__hash__()