TypeError: ประเภท unhashable: 'dict'


175

รหัสชิ้นนี้ให้ข้อผิดพลาดกับฉันunhashable type: dictทุกคนสามารถอธิบายให้ฉันได้ว่าอะไรคือทางออก

negids = movie_reviews.fileids('neg')
def word_feats(words):
    return dict([(word, True) for word in words])

negfeats = [(word_feats(movie_reviews.words(fileids=[f])), 'neg') for f in negids]
stopset = set(stopwords.words('english'))

def stopword_filtered_word_feats(words):
    return dict([(word, True) for word in words if word not in stopset])

result=stopword_filtered_word_feats(negfeats)


3
มันจะมีประโยชน์ในการแสดงรายงานข้อผิดพลาดเพื่อให้เราสามารถดูว่าบรรทัดใดมีปัญหา ...
drevicko

คำตอบ:


248

คุณกำลังพยายามที่จะใช้dictเป็นกุญแจสำคัญไปยังอีกหรือในdict setที่ใช้งานไม่ได้เนื่องจากกุญแจต้องถูกแฮช ตามกฎทั่วไปวัตถุที่เปลี่ยนแปลงไม่ได้ (สตริง, จำนวนเต็ม, ลอย, frozensets, tuples ของ immutables) เท่านั้นที่สามารถแฮชได้ (แม้ว่าจะมีข้อยกเว้นก็ตาม) ดังนั้นนี่ใช้ไม่ได้:

>>> dict_key = {"a": "b"}
>>> some_dict[dict_key] = True
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

ในการใช้ dict เป็นกุญแจคุณจะต้องเปลี่ยนเป็นสิ่งที่อาจถูกแฮชก่อน หาก dict ที่คุณต้องการใช้เป็นคีย์ประกอบด้วยค่าที่ไม่เปลี่ยนรูปแบบเท่านั้นคุณสามารถสร้างการนำเสนอที่แฮชได้เช่นนี้:

>>> key = frozenset(dict_key.items())

ตอนนี้คุณสามารถใช้keyเป็นกุญแจในdictหรือset:

>>> some_dict[key] = True
>>> some_dict
{frozenset([('a', 'b')]): True}

แน่นอนว่าคุณต้องทำแบบฝึกหัดซ้ำทุกครั้งที่คุณต้องการค้นหาบางสิ่งโดยใช้ dict:

>>> some_dict[dict_key]                     # Doesn't work
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> some_dict[frozenset(dict_key.items())]  # Works
True

หากdictคุณต้องการใช้เป็นคีย์มีค่าที่เป็นตัวเองและ / หรือรายการคุณต้อง "หยุด" คีย์ซ้ำในอนาคตซ้ำ ๆ นี่คือจุดเริ่มต้น:

def freeze(d):
    if isinstance(d, dict):
        return frozenset((key, freeze(value)) for key, value in d.items())
    elif isinstance(d, list):
        return tuple(freeze(value) for value in d)
    return d

2
ขอบคุณมันใช้งานได้ แต่ยังคงได้รับข้อผิดพลาดหากค่าเป็น dict หรือรายการ (unhashable) ตอนนี้ฉันกำลังใช้ hash (str (my_dict)) ทำงานได้ดีสำหรับฉัน
Steven Du

7
เพียงโน้ต @StevenDu พจนานุกรมไม่รับประกันการสั่งซื้อดังนั้นstr(my_dict)สามารถส่งกลับสองสายที่แตกต่างกันสำหรับ dicts (หรือที่แตกต่างกัน แต่เทียบเท่า) ที่แตกต่างกัน
K Raphael

1
การแปลงกลับ frozenset dict(the_frozenset)ผลให้กิงดิคโทรเพียง
ผู้ใช้

4
ดูเหมือนว่าสำหรับฉันแล้วfrozenset(dict_key.items())ปัญหาที่อาจเกิดขึ้นในสอง dicts ที่มีเนื้อหาเดียวกัน แต่ลำดับการแทรกที่แตกต่างกันอาจไม่ส่งผลให้คีย์เดียวกัน การเพิ่มการเรียกไปยังการเรียง () ดูเหมือนจะเป็นไปตามลำดับ เช่นกันfrozenset(sorted(dict_key.items()))นอกจากนี้ frozenset ดูเหมือนเป็นทางเลือกแปลก ๆ เนื่องจากเซตนั้นไม่มีการเรียงลำดับอย่างชัดเจน มันอาจใช้งานได้ดีในทางปฏิบัติ แต่ tuple ดูเหมือนจะเป็นทางเลือกที่สมเหตุสมผลกว่าสำหรับฉัน ฉันไปกับtuple(sorted(dict_key.items()))
Jason Heiss

เห็นด้วยกับ @JasonHeiss
3732361

6

ทางออกที่เป็นไปได้อาจจะใช้วิธี JSumps dumps () เพื่อให้คุณสามารถแปลงพจนานุกรมเป็นสตริง ---

import json

a={"a":10, "b":20}
b={"b":20, "a":10}
c = [json.dumps(a), json.dumps(b)]


set(c)
json.dumps(a) in c

ผลผลิต -

set(['{"a": 10, "b": 20}'])
True

2
มันควรจะเป็นไม่ได้dumps dump
Kushan Gunasekera
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.