1. ホーム
  2. python

eq__` を定義した型はハッシュ化できない?

2023-07-24 05:01:11

質問

私のプログラムのPython 3.1フォークに機能を移植する際に、奇妙なバグが発生しました。私はそれを次の仮説に絞り込みました。

Python 2.x とは対照的に、Python 3.x では、もしオブジェクトが __eq__ メソッドを持つ場合、それは自動的にハッシュ化不可能になります。

これは本当ですか?

Python 3.1ではこうなっています。

>>> class O(object):
...     def __eq__(self, other):
...         return 'whatever'
...
>>> o = O()
>>> d = {o: 0}
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    d = {o: 0}
TypeError: unhashable type: 'O'

続いての質問は、私の個人的な問題をどのように解決するかということです。私はあるオブジェクト ChangeTracker を格納する WeakKeyDictionary を格納し、それぞれのオブジェクトに対して過去のある時点におけるピックルダンプの値を与えています。既存のオブジェクトがチェックインされるたびに、チェンジトラッカーはその新しいピクルスが古いものと同じかどうか、つまりそのオブジェクトがその間に変更されたかどうかを表示します。問題は、与えられたオブジェクトがライブラリにあるかどうかさえチェックできないことです。なぜなら、そのオブジェクトはハッシュ化できないという例外を発生させるからです。(それは __eq__ メソッドを持っているからです)。どのように私はこれを回避することができますか?

どのように解決するのですか?

はい、もしあなたが __eq__ を定義すると、デフォルトの __hash__ (すなわち、メモリ上のオブジェクトのアドレスをハッシュする) がなくなります。これは、ハッシュが等価である必要があるため重要です。つまり、等しいオブジェクトは同じハッシュである必要があります。

解決策は簡単で、単に __hash__ の定義と一緒に __eq__ .