Python中,内置类型set和frozenset用来表示集合,我们首先查看这两个类型支持的特殊对象,从而可以理解他们的特性。
>>> dir(set) ['__and__', '__class__', '__cmp__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', ...] >>> >>> dir(frozenset) ['__and__', '__class__', '__cmp__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', ...]
set类型支持:
- x in s :判断x是否在s中,因为set对象支持特殊方法__contains__()
- len(s):计算set对象中元素的个数,因为set对象支持特殊方法__len__()
- for x in s :遍历s,即s是可迭代的,因为set对象支持特殊方法__iter__()
set类型的对象不支持:
- 索引(indexing):试图执行s[0]之类的操作将会抛出异常TypeError
- 切片(slice):试图执行s[:]之类的操作将会抛出异常TypeError,因为可以看到set类型并不支持特殊方法__getitem__()
- 哈希(hash):因为set对象的__hash__()方法是None,等于不支持。
此外,Python中另一个重要的内置类型是frozenset:
- frozenset对象是不可变的(即不支持set对象的那些 mutating 方法)
- frozenset对象有哈希值(从而可以作为字典的键和其他set对象的元素)。
例1. frozenset类型支持的非特殊方法
>>> dir(frozenset) [..., 'copy', 'difference', 'intersection', 'isdisjoint', 'issubset', 'issuperset', 'symmetric_difference', 'union'] >>> dir(set) [..., 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']
可见frozenset支持与set相同的non-mutating方法,而set支持的可变方法,frozenset则不支持。
例2. 对frozenset与set类型进行哈希运算的结果
>>> s1 = frozenset('123') >>> s2 = set('123') >>> hash(s1) -98267375 >>> hash(s2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'set'
可见frozenset是hashable对象,可以作为字典的键
例3. 将frozenset和set实例作字典键
>>> d= {s1:1} >>> d= {s2:2} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'set'
例4. 为什么set对象是不可哈希的
>>> dir(set) ['__and__', '__class__', '__cmp__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__ , '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__ior__', '__isub__' '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', __reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__size f__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'd fference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issu erset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update'] >>> type(set.__hash__) <type 'NoneType'>
我们看到,原来set对象没有__hash__()方法(__hash__方法是个None对象),所以它并不支持哈希运算。
non-mutating方法
s.copy()
返回集合s的浅拷贝。
s.difference(s1)
返回集合s中不在集合s1中的元素的集合,即s-s1。
s.intersection(s1)
返回s与s1的交集。即s&s1.
s.issubset(s1)
判断s是不是s1的子集。
s.issuperset(s1)
判断s是不是s1的超集。
s.symmetric_difference(s1)
返回由要么在s中,要么在s1中,但不同时在s和s1中的元素组成的集合。即s^s1。
例:对称差集
1 >>> s 2 set([1, 2, 3, 5]) 3 >>> s1 4 set([1, 2, 3, 4]) 5 >>> s.symmetric_difference(s1) 6 set([4, 5])
s.union(s1)
返回s和s1的并集。即s|s1。
mutating 方法
s.add(x)
将x添加到集合s中,如果s中已经有x,则该操作没有影响。
s.clear()
清空集合s。
s.discard(x)
从集合s中删除x,如果x不在s中,该操作没有影响。
s.pop()
返回并删除集合s中的任意一个元素。
s.remove(x)
区别于s.discard(x),当x在集合S中时,二者效果相同,但当x不在集合S中时,remove(x)抛出异常:KeyError;而discard(x)没有影响。
s.difference_update(s1)
即:s -= s1
s.intersection_update(s1)
即:s &= s1
s.symmetric_difference_update(s1)
即:s ^= s1
s.update(s1)
即:s |= s1
使用运算符进行集合的运算和使用函数的功能相同,当使用(增强)运算符时,两端的运算数都得是set或frozenset,
使用函数进行集合运算时,s1只要是元素可哈希的可迭代对象就行。