2011-02-09 14 views
9

私はオブジェクトをPython辞書のキーとして使用しようとしていますが、それは私がかなり理解できないように動作しています。Python辞書のキーとしてのオブジェクト

まず私は、キーとしての私のオブジェクトと辞書を作成します。

package_disseminators = { 
    ContentType("application", "zip", "http://other/property") : "one", 
    ContentType("application", "zip") : "two" 
} 

は今の鍵であるものと「同じ」である別のオブジェクトを作成します。

content_type = ContentType("application", "zip", "http://other/property") 

IカスタムたContentTypeオブジェクト__eq__方法は__str__値を比較するように__eq__およびカスタム__str__方法を与えています。今

、いくつかの対話的なPython:

>>> for key in package_disseminators: 
...  if key == content_type: 
...    print "match" 
...  else: 
...    print "no match" 
... 
no match 
match 

>>> content_type in package_disseminators.keys() 
True 

オクラホマので、それはそう、私の物のように見える間違いなくキーとして適切に識別されている:

>>> package_disseminators[content_type] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
KeyError: (& (type="application/zip") (packaging="http://other/property")) 

のErを... OK?したがって、content_typeはpackage_disseminators.keys()リストにありますが、キーではありませんか?

>>> package_disseminators.has_key(content_type) 
False 

明らかにそうではありません。

私は、リストの真の "in"ステートメントと実際にはdictのキーを調べることの間で、Pythonが等価性を判定するために使う比較プロセスが異なると推測します。任意のヒントや洞察?

答えて

17

Pythonドキュメントから:

辞書のキーはほとんど 任意の値です。 ハッシュ可能でない値、つまり、 リスト、辞書または(値 によってではなく、オブジェクトの同一性によって比較される)他の可変 型を含む値を キーとして使用されなくてもよいです。次のように

Hashableが定義されている

オブジェクトは、その 寿命の間に変化しないハッシュ 値を有する場合(それは__hash__() 方法を必要とする)ハッシュ可能であり、他と比較することができます オブジェクト(__eq__()または __cmp__()メソッドが必要です)。等しいかどうかを比較するHashableオブジェクトのハッシュ値は同じ でなければなりません。

Hashabilityは、 ハッシュ値を内部的に使用するため、オブジェクトに 辞書キーとセットメンバー としてオブジェクトを使用可能にします。

あなたはこれをしたいのであれば、あなたのオブジェクトのデフォルト__hash__()方法を(さらに説明は以下のスティーブンRumbalskiからのコメントを参照)をオーバーライドする必要があります。


>>> content_type in package_disseminators.keys() 
True 

私はdict.keys()のリストを返し、__contains__はおそらく平等のためではなく、同じハッシュを調べるので、この作品とします。

+6

さらに詳しい説明:あなたのオブジェクトにはすでに 'object'から継承された' __hash__'メソッドがあります。しかし、デフォルトの実装では各インスタンスに固有の値が返されるため、より良い実装を提供しない限り、2つの等しいインスタンスは異なるハッシュを持ちます。 'has_key'はハッシュ値を比較し、' in'チェックが等しいかどうかチェックするので、 'has_key'は失敗し、inは成功します。 –

+0

こんにちは。大変、ありがとう、大変感謝しています! –

11

dictsはフードの下のハッシュテーブルなので、それを動作させるには__eq____hash__の両方を定義する必要があります。

親指の基本的なルールは次のとおりです。__eq__が等しい比較オブジェクトの場合

  • __hash__は同じハッシュを返す必要があります。あなたの説明から

def __hash__(self): 
    return hash(str(self)) 

のようなものが動作するはずです。

+0

'__hash__'の実装に感謝します!残念ながら、質問には2つの正解を割り当てることはできませんが、あなたと他者の組み合わせは必要なものすべてです。 Cheers、R. –