Python,TypeError:不可哈希类型:'list'
- 2025-02-20 09:24:00
- admin 原创
- 78
问题描述:
我的程序中出现以下错误。回溯:
Traceback (most recent call last):
File "C:Python33ArchivePythonGrafosAlpha.py", line 126, in <module>
menugrafos()
File "C:Python33ArchivePythonGrafosAlpha.py", line 97, in menugrafos
zetta = Beta.caminhografo(grafo,va,vb)
File "C:Python33ArchivePythonGrafosBeta.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
解决方案 1:
问题是您不能使用 alist
作为 a 中的键dict
,因为dict
键必须是不可变的。请改用元组。
以下是一个列表:
[x, y]
这是一个元组:
(x, y)
请注意,在大多数情况下,(
和)
是可选的,因为,
实际上定义了一个元组(只要它没有被[]
或包围{}
,或者被用作函数参数)。
你可能会发现Python 教程中有关元组的部分很有用:
尽管元组看起来与列表相似,但它们通常用于不同的情况和目的。元组是不可变的,通常包含一个异构元素序列,可通过解包(请参阅本节后面的内容)或索引(或者在命名元组的情况下甚至通过属性)访问。列表是可变的,其元素通常是同质的,可通过迭代列表来访问。
在字典部分:
与通过数字范围进行索引的序列不同,字典是通过键进行索引的,键可以是任何不可变类型;字符串和数字始终可以作为键。如果元组仅包含字符串、数字或元组,则可以将其用作键;如果元组直接或间接包含任何可变对象,则不能将其用作键。您不能将列表用作键,因为可以使用索引分配、切片分配或 append() 和 extend() 等方法就地修改列表。
如果你想知道错误信息的含义,它抱怨因为列表没有内置的哈希函数(根据设计),并且字典是作为哈希表实现的。
解决方案 2:
如果您是因为标题中的错误而看到这篇文章,那么除了 OP 的问题(其中列表被用作字典的键)之外,还有其他几种情况可能会发生这种情况。
1. 将列表传递到集合中
就像为什么列表不能作为字典的键一样,列表也不能作为集合的元素。如果要向其中添加元组,它也不应该包含列表。
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 操作中用作分组器。解决方案与上述类似,将列表转换为元组,然后使用元组的列进行 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 索引可以包含列表作为值,但如果您尝试索引该行,则会抛出此错误。解决方案是将列表转换为元组或简单地“清理”数据(索引可能一开始就不应该包含列表/元组),例如将其转换为 MultiIndex。
df = pd.DataFrame({'group': range(3)}, index=[['a'], 'b', 'c'])
df.loc['b'] # TypeError
4.collections.Counter
在包含列表的对象上调用
因为Counter
创建了一个类似字典的对象,所以出于同样的原因,每个值都应该是不可变的,所以如果一个对象包含一个列表,就会显示此错误。一个解决方案可能是将列表转换为元组
from collections import Counter
lst = ['a', 'b', ['c']]
Counter(lst) # TypeError
Counter(['a', 'b', ('c',)]) # OK
扫码咨询,免费领取项目管理大礼包!