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只要是元素可哈希的可迭代對象就行。