TypeError:无法散列的类型:'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 2015年

Answers:


248

您正在尝试将a dict用作另一个dict或in的键set。那是行不通的,因为密钥必须是可哈希的。通常,只有不可变的对象(字符串,整数,浮点数,frozensets,不可变的元组)才是可哈希化的(尽管可能有例外)。因此,这不起作用:

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

要将字典用作键,您需要将其转换为可能首先进行哈希处理的东西。如果要用作键的字典仅由不可变值组成,则可以像这样创建可散列的表示形式:

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

现在,您可以keydict或中用作键set

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

当然,每当要使用字典查找某些内容时,都需要重复练习:

>>> 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
谢谢,它可以工作,但是如果值是字典或列表(无法哈希),仍然会出错,现在我正在使用hash(str(my_dict)),对我来说很好。
史蒂文·杜

7
请注意,@ StevenDu词典不保证顺序,因此str(my_dict)对于相同(或不同但等效)的字典,可能会返回两个不同的字符串
K Raphael

1
要将结果的Frozenset转换回dict,只需调用dict(the_frozenset)
用户

4
在我看来,frozenset(dict_key.items())潜在的问题在于内容相同但插入顺序不同的两个字典可能不会产生相同的键。依次添加对sorted()的调用。例如frozenset(sorted(dict_key.items())),鉴于setset是明确无序的,freezeset似乎是一个奇怪的选择。在实践中,它可能工作得很好,但是对我来说,元组似乎是一个更合乎逻辑的选择。我去了tuple(sorted(dict_key.items()))
贾森·海斯

同意@JasonHeiss
user3732361

6

一个可能的解决方案可能是使用JSON 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.