类型错误:不可散列的类型:'dict'

2025-01-16 08:38:00
admin
原创
109
摘要:问题描述:这段代码给了我一个错误TypeError: unhashable type: dict 谁能向我解释一下解决方案是什么?negids = movie_reviews.fileids('neg') def word_feats(words): return dict([(word, True)...

问题描述:

这段代码给了我一个错误

TypeError: 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)

解决方案 1:

您尝试将 a 用作另一个或 a 中的dict键。这行不通,因为键必须是可哈希的。一般来说,只有不可变对象(字符串、整数、浮点数、冻结集、不可变元组)才是可哈希的(尽管可能存在例外)。所以这行不通:dict`set`

>>> 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())

现在您可以在 a或中使用它key作为键:dict`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:

一种可能的解决方案可能是使用 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

解决方案 3:

发生这种情况是因为我在用 Typescript 思考,并尝试设置如下 python 字典:

thing = { 'key': 'value' }
other_thing = {'other_key': 'other_value'}
my_dictionary = { thing, other_thing }

然后我尝试:

my_dictionary = { thing: thing, other_thing: other_thing }

...仍然没有效果

最终起作用的是......

my_dictionary = { 'thing': thing, 'other_thing': other_thing }

有趣的是,我们如何习惯不同语言的小语法技巧......

解决方案 4:

如果您尝试将一个字典用作另一个字典的键(例如{{}: 1}),或者将一个字典添加到集合(例如{{}}),或者检查 set/dict_keys 中是否存在字典(例如{} in set()),或者使用一列字典作为 pandas groupby 中的分组器,就会发生此错误。

可能的解决方案:

1. dict.items()->tuple

如果字典的插入顺序很重要(如果转换为冻结集,则会丢失),则重构代码以将用作字典键/添加到集合中的字典转换为元组。例如,OP 中的问题是尝试使用字典(从word_feats函数返回)作为另一个字典的键。例如,

# dict as key of another dict
d1 = {'a': 1, 'b': 2}
d2 = {d1: 3}                                # <--- TypeError: unhashable type: 'dict'
d2 = {tuple(d1.items()): 3}                 # <--- OK

# dicts in a set
st = {d1, d2}                               # <--- TypeError: unhashable type: 'dict'
st = {tuple(x.items()) for x in (d1, d2)}   # <--- OK

# membership tests
d1 in d2                                    # <--- TypeError: unhashable type: 'dict'
tuple(d1.items()) in d2                     # True

因此,对于 OP 中的示例,返回 a 而不是 可以dict解决tuple问题。

def word_feats(words):
    return dict([(word, True) for word in words])     # <--- TypeError

def word_feats(words):
    return tuple((word, True) for word in words)      # <--- OK

如果您尝试使用@functools.lru_cache()装饰器缓存从函数返回的字典并收到此错误,则此解决方案很有用。重构函数以返回元组可解决此错误。

2 dict.->str

另一种方法是简单地将字典转换为字符串。与 类似tuple(),它保留了插入顺序。然后,如果需要将字符串化的键转换回字典,ast.literal_eval()可以使用标准库来恢复它。

import ast

d1 = {'a': 1, 'b': 2}
d2 = {str(d1): 3}                               # {"{'a': 1, 'b': 2}": 3}

str(d1) in d2                                   # True

[ast.literal_eval(key) for key in d2.keys()]    # [{'a': 1, 'b': 2}]

3. dict.items()->frozenset

由于冻结集不保留顺序,因此如果你想将字典添加到集合中,比如在列表中查找唯一字典,那么这种方法就很理想。然后,要从冻结集中恢复原始字典,请调用dict()每个冻结集。例如,

lst = [{1:3, 2:0}, {2:0, 1:3}, {2:3}]      # list of dicts
set(lst)                                   # <--- TypeError: unhashable type: 'dict'

st = {frozenset(d.items()) for d in lst}   # convert each dict into a frozenset
# convert back into a list of unique dicts
[dict(d) for d in st]                      # [{2: 3}, {2: 0, 1: 3}]

正如上面最后一行代码的输出所示,lst[0]和中只有一个lst[1]被正确保留,因为lst[0]==lst[1]为 True。

4 dict.->json.dumps()

如果字典是 json 可序列化的,那么转换为 json 对象也可用于在列表中查找唯一字典。如果要确保键的顺序无关紧要,请使用sort_keys=的参数json.dumps()。但是,需要注意的一件重要事情是 json 要求键是字符串,因此如果键是数字(如下所示),则在存在非字符串键的情况下,转换为 json 并转换回字典可能无法恢复原始字典。

import json
lst1 = [{1:3, 2:0}, {2:0, 1:3}]
[json.loads(j) for j in {json.dumps(d, sort_keys=True) for d in lst1}] 
# [{'1': 3, '2': 0}]

解决方案 5:

要获得一组字典(由于字典是可变的,所以无法创建),我建议您改用字典的字典。然后您可以将其与@StevenDu 的建议结合起来

mydict: Dict[int, dict] = {}
d1 = {'a': 1, 'b': 2}
mydict[hash(str(d1))] = d1

请注意,您可以使用任何自定义方式(而不是“hash(str(d1))”来获取字典的唯一键。

解决方案 6:

使用嵌套函数将嵌套字典中的字典转换为元组。

def make_hashable(d: dict[str, Any]) -> tuple:
"""Convert a dictionary, which is un-hashable into a tuple which is a hashable form."""
return tuple(
    sorted(
        (k, make_hashable(v)) if isinstance(v, dict) else (k, v)
        for k, v in d.items()
    )
)

解决方案 7:

def frozendict(d: dict):
    keys = sorted(d.keys())
    return tuple((k, d[k]) for k in keys)

实现上述函数返回一个不可变的结构,我们更喜欢对键进行排序以防止无序迭代。

解决方案 8:

有一个很好的包叫frozendict

pip3 install frozendict
from frozendict import frozendict

然后要么

d = frozendict(role="user", content=prompt)

或者

d = frozendict(my_dict)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用