Python set([])は、2つのオブジェクトが等しいかどうかをどのようにチェックしますか?これをカスタマイズするには、オブジェクトでどのメソッドを定義する必要がありますか?


83

Pythonで「コンテナ」オブジェクトまたはクラスを作成する必要があります。これは、私が定義した他のオブジェクトの記録を保持します。このコンテナの要件の1つは、2つのオブジェクトが同一であると見なされた場合、1つ(いずれか1つ)が削除されることです。私が最初に考えたのはset([])、この要件を満たすために、を含むオブジェクトとしてを使用することでした。

ただし、セットは2つの同一のオブジェクトインスタンスの1つを削除しません。作成するには何を定義する必要がありますか?

これがPythonコードです。

class Item(object):
  def __init__(self, foo, bar):
    self.foo = foo
    self.bar = bar
  def __repr__(self):
    return "Item(%s, %s)" % (self.foo, self.bar)
  def __eq__(self, other):
    if isinstance(other, Item):
      return ((self.foo == other.foo) and (self.bar == other.bar))
    else:
      return False
  def __ne__(self, other):
    return (not self.__eq__(other))

通訳

>>> set([Item(1,2), Item(1,2)])
set([Item(1, 2), Item(1, 2)])

__eq__()によって呼び出されるx == y、が集合によって呼び出されるメソッドではないことは明らかです。何と呼ばれていますか?他にどのような方法を定義する必要がありますか?

注:Itemsは変更可能である必要があり、変更される可能性があるため、メソッドを提供できません__hash__()。これがそれを行う唯一の方法である場合、不変Itemのを使用するために書き直します。


1
これと同じ問題がありました。コード内で少量のデータを操作していると思います。これはおそらくデータベースの使用には適していません。セットを作成してC ++でコンパレータ関数を定義できたことを覚えています。また、Javaも信じていますが、Pythonの辞書オブジェクトでこれを実行できるようには見えません。誰かがこれを行うことができるPythonで「セット」ライブラリを書いたようですが、私はそれを知りません。
Chris Dutrow 2013年

回答:


32

私はあなたが__hash__()方法を提供しなければならないのではないかと心配しています。ただし、の可変属性に依存しないようにコーディングすることはできますItem


3
< docs.python.org/reference/… >ここの2番目の段落では、__hash__()不変オブジェクトに対してのみ定義する必要があることを指摘しています。
エイダ

1
@Nathanael:オブジェクトを変更する必要がある場合は、frozenset()やset()のように、オブジェクトの不変のコピーを作成できます。
嘘ライアン

2
@ Nathanael-どのように電話し__eq__ますか?それらの(1,2)属性を比較しますか?次に、__hash__メソッドでも(1,2)のハッシュを返す必要があります。
eumiro 2010年

または、fooとbarはどちらも不変なので、__ hash __()はfooとbarのハッシュの合計を返すことができますか?いいえ...合計は信頼できません... fooが1で小節2の場合、それは小節を1に、fooを2に等しくなります。これは間違っています。この目的で使用できる数学関数は何ですか?モジュロまたは除算が機能するはずです。
エイダ

1
ナタナエル:ビルトインを使用してhashください:hash((self.foo, self.bar))。これは、ニーズに適したタプルのハッシュを使用します。(比較の__eq__観点から書くこともできtupleます。)
Pi Delport 2010年

73

はい、__hash__()すでに提供しているメソッドと比較演算子が必要です。

class Item(object):
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar
    def __repr__(self):
        return "Item(%s, %s)" % (self.foo, self.bar)
    def __eq__(self, other):
        if isinstance(other, Item):
            return ((self.foo == other.foo) and (self.bar == other.bar))
        else:
            return False
    def __ne__(self, other):
        return (not self.__eq__(other))
    def __hash__(self):
        return hash(self.__repr__())

3
Pythonの3では、あなたは必要としない__ne__、とさえ2.xの中で、あなたが定義するべきではない__ne__という点で__eq__stackoverflow.com/a/30676267/5337834
John Strood 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.