3

私は私の同僚と、すべてのPythonクラスが本当にハッシュ可能である必要があるかどうかについて議論しています。シンボリック式(SymPyに似たもの)を保持するこのクラスがあります。

私の主張は、2つの式が等しいかどうかを比較できないため、ハッシュは許可されるべきではないということです。たとえば、式'(x)'と'(1 * x)'は等しく比較できますが、'sqrt(x * x * x)'と'abs(x)* sqrt(x)'は等しくない場合があります。したがって、'hash()'は、シンボリック式で呼び出されたときにエラーをスローする必要があります。

彼の主張は、すべてのクラスを辞書とセットのキーとして使用できるようにする必要があるというものです。したがって、それらもハッシュ可能である必要があります。(私は今彼の口に言葉を入れています、彼はそれをよりよく説明したでしょう。)

誰が正しいですか?ハッシュしようとするとエラーをスローするクラスがないのは非Pythonですか?

4

4 に答える 4

4

ハッシュ関数は、明確に定義された同等性テストがあり、同等性テストで考慮される情報が不変である場合にのみ役立ちます。

デフォルトでは、すべてのユーザー定義クラスはオブジェクトIDによって比較され、id()ハッシュ値として使用されます。演算子をオーバーライドしない場合、==この動作を変更する理由はめったにありません。をオーバーライド==、この演算子で考慮される情報が不変である場合(つまり、インスタンスのリフト中に変更できない場合)、ハッシュ関数を定義してインスタンスをハッシュ可能にすることもできます。

あなたの質問から、私はこれらの条件が成り立つかどうかを完全に知ることはできません。クラスをハッシュ可能にするのは「Pythonic」または「Unpythonic」ではありません。問題は、クラスのセマンティクスがハッシュを許可するかどうかです。

于 2012-07-03T18:18:18.590 に答える
3

ハッシュ化できない組み込みのPythonタイプはたくさんあります。したがって、クラスがハッシュ可能でないことは完全にPythonicです。

提供する例は、ハッシュ可能なクラスを作成する際の問題の良い例です。オブジェクトをディクショナリのキーとして使用するには、との両方__hash__()を実装する必要があるため__eq__()です。平等を確実に判断できない場合、ハッシュ可能性にはとにかく実質的な利点はなく、それを実装することは無駄な労力です。

于 2012-07-03T18:18:49.460 に答える
3

私がここで見ている問題は、あなたが平等の2つの異なる概念で働いているということです。私があなたのコメントを正しく理解している場合、あなたは2つの引数を組み合わせた__eq__を返すようにオーバーライドしました。上記の式が(ある意味で)Trueと評価された場合、2つの式は等しくなります。また、式クラスが( Python 3で)式がtrueの場合に返されるように実装されている場合、表面的にはこれは正常に機能するはずです。==__nonzero____bool____nonzero__True

しかし実際には、あなたが定義した平等の概念は、Pythonで機能している通常の平等の概念とは非常に異なる概念であるように思われます。ハッシュ可能性の基本的な要件は、2つのアイテムが等しいと評価された場合、それらは完全に交換可能である必要があるということです。また、2つの式オブジェクトが「等しい」と評価される場合もありますが、それらが交換可能かどうかはわかりません。結局のところ、同じ結果に評価されますが、それらは同一ではありませ5 + 5?そして、これらの2つの式を考えると、多くの人が辞書内の2つの別々のビンにハッシュすることを期待していると思います。8 + 2

__eq__ただし、より一般的な定義を与えなければ、その動作は困難です。そして、ドキュメントが言うように、「等しいと比較するハッシュ可能なオブジェクトは、同じハッシュ値を持たなければなりません。」したがって、とが等しいと__eq__言う場合、それらは同じ値にハッシュする必要があります。つまり、式を現在のようにハッシュ可能にするには、等しいと評価されるすべての式の標準形を決定できるを選択する必要があります。それは私にはひどく難しいように聞こえます。5 + 58 + 2__hash__

つまり、これらの式が不変であり、式が同一である__eq__場合に戻るように再定義する場合(「等しい」よりも強い要件)、ハッシュ可能にするのに問題はありません。一方、ハッシュ不可能な不変型には何の問題もありません。また、を再定義せずに式をハッシュ可能にしようとすることはお勧めしません。True__eq__

__eq__つまり、すべては、型にはまらない方法でどれだけひどく定義したいかにかかっています。バランスをとると、__eq__予期しない動作が発生しないようにするために、従来の定義を使用すると思います。結局のところ、特別な場合は規則を破るほど特別ではありません

于 2012-07-03T18:54:21.617 に答える
2

あなたの理由は私が与える通常の理由ではありませんが、ハッシュできないクラスを持つことは確かに非Python的ではありません。クラスがハッシュ不可である可能性がある主な理由は、クラスが可変であるため、そのコアデータ自体がハッシュ不可であるためです。これは、たとえば、dictまたはlistをラップするクラスの場合です。

私は平等の比較についてあなたの論理に完全には従いません。式を同等と比較することはできないと言いますが、特定の式は同等と比較される場合とされない場合があります。それらを同等に比較することはできますか、またはできませんか?できない場合は、それらが等しいか等しくないかを比較すると言っても意味がありません。

于 2012-07-03T18:18:14.433 に答える