【问题标题】:TypeError : Unhashable typeTypeError : 不可散列的类型
【发布时间】:2011-07-19 21:01:58
【问题描述】:

我正在尝试获取元组列表:类似于[ [(1,0),(2,0),(3,0)],[(1,1),(2,1),(3,1)....]] 我用了这个说法

set([(a,b)for a in range(3)]for b in range(3))

但它给了我一个错误

TypeError: unhashable type: 'list'

我有 2 个问题要问 Python Guru:

a) 当我查看 Hashable 的 Python 定义时 -

“如果一个对象的哈希值在其生命周期内永远不会改变,那么它就是可哈希的(它需要一个hash()方法)”

当我对上面的表达式使用 dir 函数时

dir([(a,b)for a in range(3)]for b in range(3))

似乎说__hash__ 在那里。那么,为什么我会收到错误消息?

我能够得到[[(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)]] 通过使用列表命令:

list(list((a,b) for a in range(3)) for bin range(3))

b)list 和 set 都将 Iterable 作为参数。为什么一个有效(列表)而另一个无效(设置)?

【问题讨论】:

    标签: python


    【解决方案1】:

    您正在通过set(...) 调用创建set,而set 需要可散列项。你不能有一组列表。因为列表不是可散列的。

    [[(a,b) for a in range(3)] for b in range(3)] 是一个列表。它不是可散列的类型。您在 dir(...) 中看到的 __hash__ 不是方法,它只是 None。

    列表推导返回一个列表,您不需要在此处显式使用列表,只需使用:

    >>> [[(a,b) for a in range(3)] for b in range(3)]
    [[(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)]]
    

    试试这些:

    >>> a = {1, 2, 3}
    >>> b= [1, 2, 3]
    >>> type(a)
    <class 'set'>
    >>> type(b)
    <class 'list'>
    >>> {1, 2, []}
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'list'
    >>> print([].__hash__)
    None
    >>> [[],[],[]] #list of lists
    [[], [], []]
    >>> {[], [], []} #set of lists
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'list'
    

    【讨论】:

    • 那么哪些类型是不可散列的?
    【解决方案2】:

    TLDR:

    - 你不能散列一个列表、一个集合或一个字典来把它放入集合

    - 你可以散列一个元组以将其放入一个集合中。

    例子:

    >>> {1, 2, [3, 4]}
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'list'
    
    >>> {1, 2, (3, 4)}
    set([1, 2, (3, 4)])
    

    请注意,哈希在某种程度上是递归的,上面的内容适用于嵌套项:

    >>> {1, 2, 3, (4, [2, 3])}
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'list'
    

    dict 键也是可散列的,所以上面的方法也适用于 dict 键。

    【讨论】:

    • 我正在使用列表列表,所以这实际上非常有用。谢谢。
    • 创建列表的元组表示比通过例如字符串表示更快。 repr( [1,2,3] ),对吧?嵌套列表呢?
    • @AlexandrNil 对于嵌套列表,您可以使用推导式,即对于二维列表,a = [[1,2],[3,4]] # a 2 by 2 matrix 可以通过 a = set(tuple(tuple(x) for x in a))) 进行转换
    【解决方案3】:

    列表是不可散列的,因为它的内容可以在其生命周期内发生变化。您可以随时更新列表中包含的项目。

    列表不使用哈希进行索引,因此它不限于可哈希项。

    【讨论】:

      【解决方案4】:

      set 不起作用的真正原因是它使用哈希函数来区分不同的值。这意味着集合只允许可散列的对象。为什么列表不可散列已经指出。

      【讨论】:

        【解决方案5】:

        ...所以你应该这样做:

        set(tuple ((a,b) for a in range(3)) for b in range(3))
        

        ...如果需要,转换回列表

        【讨论】:

          【解决方案6】:

          你会发现list 的实例不提供__hash__——相反,每个列表的属性实际上是None(试试print [].__hash__)。因此,list 是不可散列的。

          您的代码使用 list 而不是 set 的原因是因为 set 构造了一组没有重复项的项目,而列表可以包含任意数据。

          【讨论】:

            猜你喜欢
            • 2016-03-16
            • 2012-10-27
            • 2019-01-29
            • 2012-02-19
            • 1970-01-01
            • 2018-12-26
            • 2020-10-07
            • 2017-08-01
            相关资源
            最近更新 更多