5

私が正しく理解していれば、オブジェクトがコレクションのメンバーであるか「in」であるかを判断しながら、コレクション内のすべてのオブジェクトを評価するために、オブジェクトの__cmp __()関数が呼び出されます。ただし、これはセットには当てはまらないようです。

class MyObject(object):
    def __init__(self, data):
        self.data = data

    def __cmp__(self, other):
        return self.data-other.data

a = MyObject(5)
b = MyObject(5)

print a in [b]          //evaluates to True, as I'd expect
print a in set([b])     //evaluates to False

では、オブジェクトのメンバーシップはセットでどのようにテストされますか?

4

4 に答える 4

5

__hash__クラスにメソッドを追加すると、次のようになります。

class MyObject(object):
    def __init__(self, data):
        self.data = data

    def __cmp__(self, other):
        return self.data - other.data

    def __hash__(self):
        return hash(self.data)


a = MyObject(5)
b = MyObject(5)

print a in [b] # True
print a in set([b]) # Also True!
于 2010-09-09T18:45:30.390 に答える
2
>>> xs = []
>>> set([xs])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

あります。セットは、dictと非常によく似たハッシュを使用します。これはパフォーマンスを非常に向上させ(メンバーシップテストはO(1)であり、他の多くの操作はメンバーシップテストに依存します)、セットのセマンティクスにもよく適合します。セットアイテムは一意である必要があり、アイテムが異なれば異なるハッシュが生成されますが、同じハッシュが生成されます。 (理論的には)重複を示します。

デフォルト__hash__はちょうどid(これはかなりばかげたimhoです)なので、object'sを継承するクラスの2つのインスタンスが__hash__同じ値にハッシュされることはありません(アドレススペースがハッシュよりも大きい場合を除きますsizeof)。

于 2010-09-09T18:42:18.770 に答える
1

他の人が指摘したように、オブジェクトにはデフォルトIDがないため、ハッシュとしてデフォルトIDを使用し、 Nathon__hash__が提案したようにオーバーライドできますが、ドキュメントを読んでください。具体的には、いつすべきか、すべきでないかについてのポイントです。__hash__

于 2010-09-09T18:57:38.513 に答える
0

セットはバックグラウンドでdictを使用するため、「in」ステートメントは、オブジェクトがdictのキーとして存在するかどうかをチェックします。オブジェクトはハッシュ関数を実装していないため、オブジェクトのデフォルトのハッシュ関数はオブジェクトのIDを使用します。したがって、aとbは同等ですが、それらは同じオブジェクトではなく、それがテストされています。

于 2010-09-09T18:40:24.310 に答える