簡體   English   中英

密鑰不是python字典的唯一!

[英]Keys are not unique for a python dictionary!

這里有一個愚蠢的新手問題對於python字典q len(set(q.keys())) != len(q.keys()) 這甚至可能嗎?

如果違反dict的要求並更改其哈希值,就會發生這種情況。

dict使用對象時,其哈希值不得更改,並且其與其他對象的相等性不得更改。 其他屬性可能會改變,只要它們不影響它對dict的顯示方式。

(這並不意味着哈希值是絕不允許改變。這是一個常見的誤解。哈希值本身可能改變。這是唯一dict這就要求重點哈希是一成不變的,沒有__hash__本身)。

下面的代碼將一個對象添加到dict,然后從dict下面更改其散列。 q[a] = 2然后在dict中添加a新鍵,即使它已經存在; 由於哈希值已更改,因此dict未找到舊值。 這再現了你所看到的特殊性。

class Test(object):
    def __init__(self, h):
        self.h = h
    def __hash__(self):
        return self.h

a = Test(1)
q = {}
q[a] = 1
a.h = 2
q[a] = 2

print q

# True:
print len(set(q.keys())) != len(q.keys())

字典和集合的基礎代碼基本相同,因此您通常可以預期len(set(d.keys()) == len(d.keys())是一個不變量。

也就是說,set和dicts都依賴於__eq__和__hash__來識別唯一值並組織它們以進行有效搜索。 因此,如果那些返回不一致的結果(或違反“a == b暗示hash(a)== hash(b)”的規則,則無法強制執行不變量:

>>> from random import randrange
>>> class A():
    def __init__(self, x):
        self.x = x
    def __eq__(self, other):
        return bool(randrange(2))
    def __hash__(self):
        return randrange(8)
    def __repr__(self):
        return '|%d|' % self.x


>>> s = [A(i) for i in range(100)]
>>> d = dict.fromkeys(s)
>>> len(d.keys())
29
>>> len(set(d.keys()))
12

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM