理解Python集的行为

时间:2011-02-16 21:19:40

标签: python set

内置类型set的文档说:

class set([iterable])
  

返回一个新的set或frozenset对象   其元素取自   迭代。一组的元素必须   是可以洗的。

没关系,但为什么会这样做:

>>> l = range(10)
>>> s = set(l)
>>> s
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

这不是:

 >>> s.add([10])

    Traceback (most recent call last):
      File "<pyshell#7>", line 1, in <module>
        s.add([10])
    TypeError: unhashable type: 'list'

两者都是清单。在初始化期间是否发生了一些魔术

6 个答案:

答案 0 :(得分:12)

初始化集合时,您需要提供必须每个可以清除的值列表。

s = set()
s.add([10])

相同
s = set([[10]])

会抛出你现在看到的同样错误。

答案 1 :(得分:5)

In [13]: (2).__hash__
Out[13]: <method-wrapper '__hash__' of int object at 0x9f61d84>

In [14]: ([2]).__hash__ # nothing.

问题是set需要其项目可以清除,即实现__hash__魔术方法(据我所知,这用于树中的排序)。 list 实现该魔术方法,因此无法将其添加到集合中。

答案 2 :(得分:5)

在这一行:

s.add([10])

您正在尝试向列集添加列表,而不是列表的元素。如果您想要添加列表的元素,请使用更新方法。

答案 3 :(得分:1)

它的行为符合文档:set.add()添加一个元素(因为你给它一个列表,它抱怨它是不可用的 - 因为列表不好像哈希键)。如果要添加元素列表,请使用set.update()。例如:

>>> s = set([1,2,3])
>>> s.add(5)
>>> s
set([1, 2, 3, 5])
>>> s.update([8])
>>> s
set([8, 1, 2, 3, 5])

答案 4 :(得分:0)

将构造函数视为:

class Set:
    def __init__(self,l):
        for elem in l:
            self.add(elem)

关注为什么需要列表但另一方面add(element)没有关注,没有什么太有意思了。

答案 5 :(得分:0)

s.add([10])按照记录的方式工作。引发异常,因为[10]不可以删除。

初始化期间没有任何神奇的事情发生。

set([0,1,2,3,4,5,6,7,8,9])与set(范围(10))和set(xrange(10))和set具有相同的效果( ())

def foo():
    for i in (9,8,7,6,5,4,3,2,1,0):
        yield i

换句话说,要设置的arg是 iterable ,并且从iterable获取的每个值都必须是可清除的。