2016-05-04 9 views
26

私は、次の辞書にPython辞書割り当てられたすべてのキーを持っていない、またはアイテム

exDict = {True: 0, False: 1, 1: 'a', 2: 'b'} 

を作成し、私はexDict.keys()を印刷するとき、まあ、それは私に発電機を提供します。わかりましたので、私はそれをリストに強制します。それは私に与えます

[False, True, 2] 

なぜ1つではありませんか?私はexDict.items()を印刷するとき、それは私に

[(False, 1), (True, 'a'), (2, 'b')] 

を与える誰もがここで何が起こっているかについての推測を持っていますか?私は困惑している。

+2

素敵なヘッドスクラッチャー! Pythonのデザイナーは驚きを避けようとしますが、それらをすべて得ることはできません。 – alexis

+3

あなたのアイテムには、 '(True、 'a')'という値があり、これは '1'の値です。 – njzk2

答えて

28

これは、True == 1(およびFalse == 0ですが、0をキーにしていないため)に発生します。 dictは、彼らが(というよりもis)「等しい」である場合にキーが同じであると考えるので、あなたは、何とか自分のコードやデータをリファクタリングする必要があります。あなたが見ている何

+0

しかし、辞書が順序付けされていないので、どちらが表示されるのかは確実ではありません。 – heemayl

+1

確実性があるかどうかはわかりません。私はとにかくそれに頼るつもりはない。 –

+1

@heemayl dictの項目の順序は保証されていませんが、使用するキーは最初に遭遇するキーと思われます。同等の既存のものが見つかると、キーを置き換えることはありません。 –

12

Trueに等しくなるように1を強制するのpythonです。

あなたは印刷する辞書があることがわかります:

a1に割り当てることを意図したが、 Trueのための代わりに、値が aに再割り当ててしまった
False 1 
True a 
2  b 

Python 3 Documentationによれば

ブール型は、整数型のサブタイプであり、ブール値は例外があることを、ほとんどすべての状況で、それぞれ値0及び1のように振る舞います文字列に変換するとき、「偽」または「真」の文字列は、それぞれ、返されます。

重点鉱山。

注:Python 2.X TrueおよびFalseでは、この動作を保証することはできません。

5

PythonはTrueとして1を取ります。ブール型は整数型のサブタイプである

In [1]: a = {} 

In [2]: a[True] = 0 

In [3]: 1 in a.keys() 
Out[3]: True 
2

キーがすでに存在し、それが存在する場合、それは現在の値に置き換えられます場合は、dictのpythonチェックでキーと値のペアを挿入した場合。

このチェックでは、このような何かを行います。

def hash_and_value_equal(key1, key2): 
    return hash(key1) == hash(key2) and key1 == key2 

そうではないだけの値が同じでなければならないのが、また彼らのhash

>>> hash_and_value_equal(0, False) 
True 

>>> hash_and_value_equal(1, True) 
True 

、したがって、彼らは(しかしないキー)の値を置き換えます:残念ながらあなたTrue1False0は同じキーと見なされるため

>>> a = {1: 0} 
>>> a[True] = 2 
>>> a 
{1: 2} 

>>> a = {False: 0} 
>>> a[0] = 2 
>>> a 
{False: 2} 

私が示したきました手動でキーを追加する場合の手順は、dict literalを使用する場合と同じです。

dict -builtin:

>>> a = dict(((0, 0), (False, 2))) 
>>> a 
{0: 2} 

あなたは自分のクラスを記述し、辞書内の潜在的なキーとしてそれらを使用したい場合、これは非常に重要になる場合があります。 __eq____hash__これらの意志の実装に応じと同じではなく、同一のキーの値置き換えることはありません。

class IntContainer(object): 
    def __init__(self, value): 
     self.value = value 

    def __eq__(self, other): 
     return self.value == other 

    def __hash__(self): 
     # Just offsetting the hash is enough because it also checks equality 
     return hash(1 + self.value) 

>>> hash_equal(1, IntContainer(1)) 
False 

>>> hash_equal(2, IntContainer(1)) 
False 

したがって、これら置き換えることはありません、既存の整数キー:

>>> a = {1: 2, IntContainer(1): 3, 2: 4} 
>>> a 
{1: 2, <__main__.IntContainer at 0x1ee1258fe80>: 3, 2: 4} 

か何かをそれは、同一の鍵と考えられている:

class AnotherIntContainer(IntContainer): 
    def __hash__(self): 
     # Not offsetted hash (collides with integer) 
     return hash(self.value) 

>>> hash_and_value_equal(1, AnotherIntContainer(1)) 
True 

これらは現在、整数キーを置き換えます:

>>> a = {1: 2, AnotherIntContainer(1): 5} 
>>> a 
{1: 5} 

唯一本当に重要なことは、オブジェクトとそのハッシュが等しい場合、辞書キーが等しいとみなされることです。

関連する問題