Python,TypeError:不可散列类型:'列表'

6qqygrtg  于 2023-05-30  发布在  Python
关注(0)|答案(2)|浏览(327)

我在程序中收到以下错误。traceback:

Traceback (most recent call last):
File "C:\Python33\Archive\PythonGrafos\Alpha.py", line 126, in <module>
menugrafos()
File "C:\Python33\Archive\PythonGrafos\Alpha.py", line 97, in menugrafos
zetta = Beta.caminhografo(grafo,va,vb)
File "C:\Python33\Archive\PythonGrafos\Beta.py", line 129, in caminhografo
if ([vo, a]) in vat == ([vo,vq]) in vat:
TypeError: unhashable type: 'list'

该程序的目的是制作一个工作正常的邻接表,然后继续搜索顶点va和vb之间是否有路径。我在collection/defaultdict中使用了一个列表字典来适当地附加相邻的顶点。
问题出在程序末尾创建列表之后的if子句中。我找不到一种方法来正确地使用字典的if子句来查看顶点之间是否有有效的路径。此外,grafo是一个图形类。
下面是代码:

class graph:
    v = 0
    a = 0
    node = []

class vertex:
    ta = []
    adj = {}
    
def caminhografo(grafo, va, vb):
    vat = defaultdict(list)
    i = 0
    a = 0
    z = 0
    vo = int(va)
    vq = int(vb)
    vz = int(va)
    vw = int(vb)
    x = len(grafo.node)
    if vz < vw:
        for vz in range (vw+1):
            a = 0
            x = len(grafo.node)
            for a in range (x):
                if [int(vz),int(a)] in grafo.node:
                    vat[vz].append(a)                   
    if vz > vw:
        while vz > vw:
            a = 0
            x = len(grafo.node)
            for a in range (x):
                if[int(va),int(a)] in grafo.node:
                    vat[vz].append(a)
            vz = vz - 1
    a = 0
    x = len(grafo.node)
    print(vat)
    for a in range (x):
       if ([vo, a]) in vat == ([vo,vq]) in vat:
           print("""
    ==============================================
               Existe Caminho
    ==============================================
    """)
           break
       elif ([vo,a]) in vat:
           vo = a
       else:           
           print("""
    ==============================================
             Não Existe Caminho
    ==============================================
        """)
           break
iezvtpos

iezvtpos1#

问题是不能使用list作为dict中的键,因为dict键需要是不可变的。请改用元组。
这是一个列表:

[x, y]

这是一个tuple:

(x, y)

请注意,在大多数情况下,()是可选的,因为,实际上定义了元组(只要它没有被[]{}包围,或者用作函数参数)。
你可能会发现Python教程中关于元组的部分很有用:
虽然元组看起来类似于列表,但它们通常用于不同的情况和不同的目的。元组是不可变的,并且通常包含通过解包(参见本节后面的内容)或索引(甚至在namedtuples的情况下通过属性)访问的异构元素序列。列表是可变的,它们的元素通常是同构的,可以通过遍历列表来访问。
在字典部分:
与序列不同的是,序列是由一系列数字索引的,字典是由键索引的,键可以是任何不可变的类型;字符串和数字总是可以作为键。如果元组只包含字符串、数字或元组,则元组可以用作键;如果元组直接或间接地包含任何可变对象,则不能将其用作键。不能将列表用作键,因为可以使用索引赋值、切片赋值或append()和extend()等方法就地修改列表。
如果你想知道错误消息是什么意思,它是在抱怨,因为没有内置的hash function列表(根据设计),字典实现为hash tables

bvk5enib

bvk5enib2#

如果你是因为标题中的错误而到达这篇文章的,除了OP的问题(使用列表作为dict的键),还有几种情况可能会发生这种情况。

1.列表传入set

就像为什么列表不能是字典键一样,列表不能是集合元素。如果要向它添加一个元组,它也不应该包含一个列表。

s = {(1, 2), [3, 4]}    # <---- TypeError: unhashable type: 'list'
s = {(1, 2), (3, 4)}    # <---- OK

s.add((5, [6]))         # <---- TypeError because the element to be added contains a list
s.add((5, 6))           # <---- OK because (5, 6) is a tuple
2.列表上的Pandas groupby

发生此错误的另一种常见方式是,如果pandas dataframe列存储了一个列表,并在groupby操作中用作分组器。一个解决方案与上面类似,将列表转换为元组并使用元组列进行分组。

import pandas as pd
df = pd.DataFrame({'group': [[1, 2], [3, 4], [5, 6]], 'value': [0, 1, 2]})

# group  value
# [1, 2]     0
# [3, 4]     1
# [5, 6]     2

df.groupby('group')['value'].mean()                  # <---- TypeError
df.groupby(df['group'].agg(tuple))['value'].mean()   # <---- OK
#          ^^^^^^^^^^^^^^^^^^^^^^  <--- convert each list into a tuple
3. Pandas索引/列标签包含列表

Pandas列标签不能是列表(因为它类似于字典键),所以如果你试图通过列表rename()它,它会显示这个错误。一种解决方案是将列表转换为元组(甚至转换为MultiIndex)。

df = pd.DataFrame({'group': range(3)})
df.rename(columns={'group': ['col', 'one']})               # TypeError
df.rename(columns={'group': ('col', 'one')})               # OK
df.columns = pd.MultiIndex.from_tuples([('col', 'one')])   # OK

Pandas index可以包含一个列表作为一个值,但如果你试图索引该行,它会抛出这个错误。一种解决方案是将列表转换为元组或简单地“清理”数据(可能索引不应该包含列表/元组),例如将其转换为MultiIndex。

df = pd.DataFrame({'group': range(3)}, index=[['a'], 'b', 'c'])
df.loc['b']           # TypeError
4. collections.Counter在包含列表的对象上调用

因为Counter创建了一个类似于dict的对象,所以每个值都应该是不可变的,所以如果一个对象包含一个列表,就会显示这个错误。一个解决方案可能是将列表转换为元组

from collections import Counter
lst = ['a', 'b', ['c']]
Counter(lst)                  # TypeError

Counter(['a', 'b', ('c',)])   # OK

相关问题