你們好,恰逢初五迎財神,先預祝你們新年財源滾滾!!
在上一期詳解tuple元組的用法後,今天咱們來看Python裏面最後一種常見的數據類型:集合(Set)shell
與dict相似,set也是一組key的集合,但不存儲value。因爲key不能重複,因此,在set中,沒有重複的key。建立一個set,須要提供一個list做爲輸入集集合,重複元素在set中會被自動被過濾,經過add(key)方法往set中添加元素,重複添加不會有效果。若是如今你發現我講的很模糊請不要着急。稍後會有海量例子爲你們詳解。函數
總而言之,Set具備三個顯著特色:測試
如今讓咱們開啓Set奇幻之旅,我但願這篇文章是SegmentFault社區對於Set介紹最全的模範,哈哈!spa
咱們有兩種方式能夠建立一個Set,可使用內置的set()方法,或是使用中括號{}
建立模板以下:3d
x = set(<iter>) x = {<obj>, <obj>, ..., <obj>}
如今讓咱們來看例子~code
set()內置方法建立
x = set(['foo', 'bar', 'baz', 'foo', 'qux']) # 傳入List print(x) y = set(('foo', 'bar', 'baz', 'foo', 'qux')) #傳入元組 print(y) Out: {'qux', 'foo', 'bar', 'baz'} # 注意到無序了吧~ {'bar', 'qux', 'baz', 'foo'}
這裏要注意用set()內置方法建立時必定要傳遞一個能夠迭代的參數,還有從輸出結果相信你們已經發現set的第一個特色了:無序對象
字符串也是可迭代的,所以字符串也能夠傳遞給set()blog
s = 'quux' a = set(s) print(a) Out: {'u', 'q', 'x'} # 無序,惟一
這裏又體現了set的第二個特色:元素惟一性索引
{} 方法建立
>>> x = {'foo', 'bar', 'baz', 'foo', 'qux'} >>> x {'qux', 'foo', 'bar', 'baz'}
這裏考慮到以後例子太多,實在不能每次都打print啦,這種形式你們看的更清楚,這個直接用{}建立很簡單,只要傳遞進元素就行啦ip
建立空集合
Set能夠是空的。可是,請記住Python將空花括號{}解釋爲空字典,所以定義空集的惟一方法是使用set()函數
>>> x = set() >>> type(x) <class 'set'> >>> x = {} >>> type(x) <class 'dict'>
一個空集合用布爾類型顯示爲False
>>> x = set() >>> bool(x) False >>> x or 1 1 >>> x and 1 set()
對比小結
對於這兩種方法建立Set,本質區別在於如下兩點
補充說明
集合中的元素能夠是不一樣類型的對象,不必定非要是同一類型的,能夠包含不一樣類型,好比:
>>> x = {42, 'foo', 3.14159, None} >>> x {None, 'foo', 42, 3.14159}
但同時不要忘記set元素必須是不可變的。例如,元組能夠包括在集合中:
>>> x = {42, 'foo', (1, 2, 3), 3.14159} >>> x {42, 'foo', 3.14159, (1, 2, 3)}
但列表和字典是可變的,所以它們不能成爲Set的元素:
>>> a = [1, 2, 3] >>> {a} Traceback (most recent call last): File "<pyshell#70>", line 1, in <module> {a} TypeError: unhashable type: 'list' >>> d = {'a': 1, 'b': 2} >>> {d} Traceback (most recent call last): File "<pyshell#72>", line 1, in <module> {d} TypeError: unhashable type: 'dict'
len()函數返回集合中元素的數量,而in和not in運算符可用於測試是否爲Set中的元素:
>>> x = {'foo', 'bar', 'baz'} >>> len(x) 3 >>> 'bar' in x True >>> 'qux' in x False
方法和運算符
許多可用於Python其餘數據類型的操做對集合沒有意義。例如,沒法對集合創建索引或切片。可是,Python在set對象上提供了運算符,這些操做符其實不少和數學裏是如出一轍的,相信數學好的朋友們對這部分簡直不要太熟悉
因此對於Set的操做除了用普通的內置方法,咱們也可使用運算符,比較方便
Union 並集
讓咱們新建兩個Set作測試:
>>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'baz', 'qux', 'quux'}
如今咱們想求x1,x2的並集,以下圖所示:
具體實現方法以下,或是用方法,或是用操做符:
>>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'baz', 'qux', 'quux'} >>> x1.union(x2) {'foo', 'qux', 'quux', 'baz', 'bar'} >>> x1 | x2 {'foo', 'qux', 'quux', 'baz', 'bar'}
若是有兩個以上的Set也是沒有問題的,原理都是同樣的:
>>> a = {1, 2, 3, 4} >>> b = {2, 3, 4, 5} >>> c = {3, 4, 5, 6} >>> d = {4, 5, 6, 7} >>> a.union(b, c, d) {1, 2, 3, 4, 5, 6, 7} >>> a | b | c | d {1, 2, 3, 4, 5, 6, 7}
Intersection 交集
如今還讓咱們用剛纔建立好的兩個set,所求部分以下圖:
實現仍然是兩種方法: >>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'baz', 'qux', 'quux'} >>> x1.intersection(x2) {'baz'} >>> x1 & x2 {'baz'}
多個集合的狀況公示和方法依然有效,結果僅包含全部指定集合中都存在的元素。
>>> a = {1, 2, 3, 4} >>> b = {2, 3, 4, 5} >>> c = {3, 4, 5, 6} >>> d = {4, 5, 6, 7} >>> a.intersection(b, c, d) {4} >>> a & b & c & d {4}
Difference 差集
下圖所示爲x1.difference(x2)的目標結果:
>>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'baz', 'qux', 'quux'} >>> x1.difference(x2) {'foo', 'bar'} >>> x1 - x2 {'foo', 'bar'}
仍是老樣子,適用於2個及以上的集合:
>>> a = {1, 2, 3, 30, 300} >>> b = {10, 20, 30, 40} >>> c = {100, 200, 300, 400} >>> a.difference(b, c) {1, 2, 3} >>> a - b - c {1, 2, 3}
指定多個集合時,操做從左到右執行。在上面的示例中,首先計算a - b,獲得{1,2,3,300}。而後從該集合中減去c,留下{1,2,3},具體流程以下圖所示:
Symmetric Difference 對稱差集
下圖所示爲x1.symmetric_difference(x2)的目標結果:
實現方法以下;
>>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'baz', 'qux', 'quux'} >>> x1.symmetric_difference(x2) {'foo', 'qux', 'quux', 'bar'} >>> x1 ^ x2 {'foo', 'qux', 'quux', 'bar'}
老規矩,支持2個及以上set的連續操做:
>>> a = {1, 2, 3, 4, 5} >>> b = {10, 2, 3, 4, 50} >>> c = {1, 50, 100} >>> a ^ b ^ c {100, 5, 10}
當指定多個集合時,操做從左到右執行,奇怪的是,雖然 ^ 運算符容許多個集合,但.symmetric_difference()方法不容許
>>> a = {1, 2, 3, 4, 5} >>> b = {10, 2, 3, 4, 50} >>> c = {1, 50, 100} >>> a.symmetric_difference(b, c) Traceback (most recent call last): File "<pyshell#11>", line 1, in <module> a.symmetric_difference(b, c) TypeError: symmetric_difference() takes exactly one argument (2 given)
x1.isdisjoint(x2) 判斷是否相交
>>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'baz', 'qux', 'quux'} >>> x1.isdisjoint(x2) False >>> x2 - {'baz'} {'quux', 'qux'} >>> x1.isdisjoint(x2 - {'baz'}) True
從這個栗子能夠看出,若是兩個Set沒有共同元素返回True,若是有返回True,若是返回True同時也意味着
他們之間的交集爲空集,這個很好理解:
>>> x1 = {1, 3, 5} >>> x2 = {2, 4, 6} >>> x1.isdisjoint(x2) True >>> x1 & x2 set()
注意:目前尚未運算符對應這個方法
x1.issubset(x2) 判斷x1是否爲x2子集
>>> x1 = {'foo', 'bar', 'baz'} >>> x1.issubset({'foo', 'bar', 'baz', 'qux', 'quux'}) True >>> x2 = {'baz', 'qux', 'quux'} >>> x1 <= x2 False
一個集合自己固然是它本身的子集啦:
>>> x = {1, 2, 3, 4, 5} >>> x.issubset(x) True >>> x <= x True
x1<x2 判斷x1是否爲x2的真子集
首先。。。讓咱們回顧一下數學知識:真子集與子集相似,除了集合不能相同。若是x1的每一個元素都在x2中,而且x1和x2不相等,則集合x1被認爲是另外一個集合x2的真子集
換個高大上的說法也能夠:若是集合A⊆B,存在元素x∈B,且元素x不屬於集合A,咱們稱集合A與集合B有真包含關係,集合A是集合B的真子集(proper subset)。記做A⊊B(或B⊋A),讀做「A真包含於B」(或「B真包含A」)
>>> x1 = {'foo', 'bar'} >>> x2 = {'foo', 'bar', 'baz'} >>> x1 < x2 True >>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'foo', 'bar', 'baz'} >>> x1 < x2 False
雖然Set被認爲是其自身的子集,但它自己並非本身的真子集:
>>> x = {1, 2, 3, 4, 5} >>> x <= x True >>> x < x False
注意:目前尚未方法對應這個運算符
x1.issuperset(x2) 判斷x1是否爲x2的超集
>>> x1 = {'foo', 'bar', 'baz'} >>> x1.issuperset({'foo', 'bar'}) True >>> x2 = {'baz', 'qux', 'quux'} >>> x1 >= x2 False
咱們剛纔已經看到過了一個Set是它本身自己的子集,這裏也是同樣的,它同時也是本身的超集
>>> x = {1, 2, 3, 4, 5} >>> x.issuperset(x) True >>> x >= x True
x1 > x2 判斷x1是否爲x2的真超集
真超集與超集相同,除了集合不能相同。若是x1包含x2的每一個元素,而且x1和x2不相等,則集合x1被認爲是另外一個集合x2的真超集。
>>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'foo', 'bar'} >>> x1 > x2 True >>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'foo', 'bar', 'baz'} >>> x1 > x2 False
一個集合不是它本身的真超集,和真子集的原理相同
>>> x = {1, 2, 3, 4, 5} >>> x > x False
雖然集合中包含的元素必須是不可變類型,但能夠修改集合自己。與上面的操做相似,可使用多種運算符和方法來更改集合的內容。
x1.update(x2) 經過union修改集合元素
x1.update(x2) 和 x1 |= x2 做用是向集合x1中添加x2中全部x1不存在的元素。
停下3秒,我仔細讀了這句話,以爲我表達的還能夠,不知道你們讀上去繞不繞,先看例子:
>>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'foo', 'baz', 'qux'} >>> x1 |= x2 >>> x1 {'qux', 'foo', 'bar', 'baz'} >>> x1.update(['corge', 'garply']) >>> x1 {'qux', 'corge', 'garply', 'foo', 'bar', 'baz'}
x1.intersection(x2) 經過intersection修改集合元素
x1.intersection_update(x2) 和 x1 &= x2 會讓x1只保留x1和x2的交集部分:
>>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'foo', 'baz', 'qux'} >>> x1 &= x2 >>> x1 {'foo', 'baz'} >>> x1.intersection_update(['baz', 'qux']) >>> x1 {'baz'}
x1.difference_update(x2) 經過difference修改集合元素
x1.difference_update(x2) and x1 -= x2 會讓集合x1移除全部在x2出現的屬於x1的元素:
>>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'foo', 'baz', 'qux'} >>> x1 -= x2 >>> x1 {'bar'} >>> x1.difference_update(['foo', 'bar', 'qux']) >>> x1 set()
x1.symmetric_difference_update(x2) 經過對稱差集修改集合元素
這個我實在用語言解釋不清了,看例子容易懂:
>>> x1 = {'foo', 'bar', 'baz'} >>> x2 = {'foo', 'baz', 'qux'} >>> >>> x1 ^= x2 >>> x1 {'bar', 'qux'} >>> >>> x1.symmetric_difference_update(['qux', 'corge']) >>> x1 {'bar', 'corge'}
x.add(<elem> 添加元素
這個就很簡單了, 相似List:
>>> x = {'foo', 'bar', 'baz'} >>> x.add('qux') >>> x {'bar', 'baz', 'foo', 'qux'}
x.remove(<elem>) 刪除元素
若是刪除的元素不存在會拋出異常
>>> x = {'foo', 'bar', 'baz'} >>> x.remove('baz') >>> x {'bar', 'foo'} >>> x.remove('qux') Traceback (most recent call last): File "<pyshell#58>", line 1, in <module> x.remove('qux') KeyError: 'qux'
這個時候爲了不出現錯誤能夠用discard方法
>>> x = {'foo', 'bar', 'baz'} >>> x.discard('baz') >>> x {'bar', 'foo'} >>> x.discard('qux') >>> x {'bar', 'foo'}
利用pop刪除隨機元素並返回:
>>> x = {'foo', 'bar', 'baz'} >>> x.pop() 'bar' >>> x {'baz', 'foo'} >>> x.pop() 'baz' >>> x {'foo'} >>> x.pop() 'foo' >>> x set()
利用clear能夠清空一個集合:
>>> x = {'foo', 'bar', 'baz'} >>> x {'foo', 'bar', 'baz'} >>> >>> x.clear() >>> x set()
Frozen Sets是什麼東西
Python提供了另外一種稱爲凍結集合Frozen Sets的內置類型,它在全部方面都與集合徹底相同,只不過Frozen Sets是不可變的。咱們能夠對凍結集執行非修改操做,好比:
>>> x = frozenset(['foo', 'bar', 'baz']) >>> x frozenset({'foo', 'baz', 'bar'}) >>> len(x) 3 >>> x & {'baz', 'qux', 'quux'} frozenset({'baz'})
若是膽敢嘗試修改Frozen Sets:
>>> x = frozenset(['foo', 'bar', 'baz']) >>> x.add('qux') Traceback (most recent call last): File "<pyshell#127>", line 1, in <module> x.add('qux') AttributeError: 'frozenset' object has no attribute 'add' >>> x.pop() Traceback (most recent call last): File "<pyshell#129>", line 1, in <module> x.pop() AttributeError: 'frozenset' object has no attribute 'pop' >>> x.clear() Traceback (most recent call last): File "<pyshell#131>", line 1, in <module> x.clear() AttributeError: 'frozenset' object has no attribute 'clear' >>> x frozenset({'foo', 'bar', 'baz'})
基本使用舉例
Frozensets在咱們想要使用集合的狀況下頗有用,但須要一個不可變對象。
例如,若是沒有Frozen sets咱們不能定義其元素也是集合的集合(nested),由於集合元素必須是不可變的,會報錯:
>>> x1 = set(['foo']) >>> x2 = set(['bar']) >>> x3 = set(['baz']) >>> x = {x1, x2, x3} Traceback (most recent call last): File "<pyshell#38>", line 1, in <module> x = {x1, x2, x3} TypeError: unhashable type: 'set'
如今有了 Frozen sets,咱們有了解決方案:
>>> x1 = frozenset(['foo']) >>> x2 = frozenset(['bar']) >>> x3 = frozenset(['baz']) >>> x = {x1, x2, x3} >>> x {frozenset({'bar'}), frozenset({'baz'}), frozenset({'foo'})}
這一期爲你們講了太多東西,一口老血吐在鍵盤上,總結不動了
只但願這期Set詳解介紹能夠幫助到你們,若是幫到了你,就點個贊吧~~
最後再次祝你們豬年大吉!!