无法将列表转换为集合,会引发“unhashable type: 'list'”错误。

8

我正在尝试查找列表的所有子列表,这是我当前的代码。我是Python新手,不明白为什么执行 " Q3_ans=set(ans)" 会出错。我曾尝试在将列表转换为集合之前进行转换,并且它也起作用。

def f2(seq):
    '''
    This is the base case of the recursion from function all_sublists
    '''
    assert len(seq)==2
    assert isinstance(x,list)
    a,b=seq
    return [[a],[b],[a,b]]


def all_sublists(x):
    '''
    This function will generate all of the sublists of a list, not including the empty one, using recursion
    '''
    assert isinstance(x,list)
    ans=[]
    for i in range(0,len(x)-1):
        for j in range(1,len(x)):
            temp=[x[i],x[j]]
            temp=[f2(temp)]
            ans.extend(temp)
    Q3_ans=set(ans) 
    return Q3_ans

当我运行我的代码时出现了错误: y=[1,2,3,4,5]

all_sublists(y)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-108-f8b1bb0a7001> in <module>
----> 1 all_sublists(y)

<ipython-input-106-84f4f752e98e> in all_sublists(x)
     10             temp=[f2(temp)]
     11             ans.extend(temp)
---> 12     Q3_ans=set(ans)
     13     return Q3_ans

TypeError: unhashable type: 'list'

我起初想用递归,但后来我改变了主意,请不要在意这个评论。 - 家宁张
你看到了什么错误?请在你的问题中提供完整的回溯信息 在这里 - jpp
您的列表包含不可哈希化的列表。 - Thierry Lathuille
可能是重复的问题:Python:TypeError:unhashable type:'list' - Matthieu Brucher
2个回答

3
以下是问题的核心内容:
>>> set([[["a"],["b"],["a","b"]]])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

那么,这意味着什么?

set([iterable])

返回一个新的集合对象,其元素取自可迭代对象。 集合的元素必须是可哈希的

可哈希

如果对象具有永不更改的哈希值(它需要一个__hash__()方法),并且可以与其他对象进行比较(它需要一个__eq__()方法),则该对象是可哈希的。比较相等的可哈希对象必须具有相同的哈希值。

可哈希性使对象可用作字典键和集合成员,因为这些数据结构在内部使用哈希值。

Python的所有不可变内置对象都是可哈希的;可变容器(例如列表或字典)不是

关键字在于可变

可变对象可以更改其值但保持其id()。

不可变

具有固定值的对象。不可变对象包括数字、字符串和元组。这样的对象不能被更改。如果需要存储不同的值,则必须创建一个新对象。它们在需要常量哈希值的地方发挥重要作用,例如作为字典中的键。

因此,您不能将list用作set元素。 tuple可以使用:

>>> set([(("a"),("b"),("a","b"))])
{('a', 'b', ('a', 'b'))}

1
有些事情不对劲。有很多关于使用代码 set(<list>) 将列表转换为集合的引用。这怎么可能呢? - PProteus
2
@PProteus,你提到的列表转换为集合是有效的,但是这个列表不能包含更多的列表元素,即set(<list(<list>)>)会导致TypeError。尝试使用例如set([1,2,3])set([[1],2,3]) - handle

1
正如你所想象的那样,可变类型如列表无法被散列,因此无法转换为“set”。你可以尝试返回元组而不是列表;元组是列表的不可变对应物。
def f2(seq):
    assert len(seq)==2
    assert isinstance(x, tuple) # what's `x` actually?
    a, b = seq
    return ((a), (b), (a,b))

def all_sublists(x):
    assert isinstance(x, list)
    ans = []
    for i in range(0, len(x) - 1):
        for j in range(1, len(x)):
            temp = (x[i], x[j])
            temp = [f2(temp)]
            ans.extend(temp)
    Q3_ans = set(tuple(ans))
    return Q3_ans

那么

all_sublists([1, 2, 3])

您可以在文档中了解关于 元组 类型的更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接