Python 進階之路 (四) 先立Flag, 社區最全的Set用法集錦

Set是什麼

你們好,恰逢初五迎財神,先預祝你們新年財源滾滾!!
在上一期詳解tuple元組的用法後,今天咱們來看Python裏面最後一種常見的數據類型:集合(Set)shell

與dict相似,set也是一組key的集合,但不存儲value。因爲key不能重複,因此,在set中,沒有重複的key。建立一個set,須要提供一個list做爲輸入集集合,重複元素在set中會被自動被過濾,經過add(key)方法往set中添加元素,重複添加不會有效果。若是如今你發現我講的很模糊請不要着急。稍後會有海量例子爲你們詳解。函數

總而言之,Set具備三個顯著特色:測試

  • 無序
  • 元素是獨一無二的,不容許出現重複的元素
  • 能夠修改集合自己,但集合中包含的元素必須是不可變類型

如今讓咱們開啓Set奇幻之旅,我但願這篇文章是SegmentFault社區對於Set介紹最全的模範,哈哈!spa

定義一個Set

咱們有兩種方式能夠建立一個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,本質區別在於如下兩點

  1. set()的參數是可迭代的。它會生成要放入集合中的全部元素組成的List。
  2. 花括號 {} 中的對象完整地放入集合中,即便它們是可迭代的。
補充說明

集合中的元素能夠是不一樣類型的對象,不必定非要是同一類型的,能夠包含不一樣類型,好比:

>>> 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'

Set大小以及成員

len()函數返回集合中元素的數量,而in和not in運算符可用於測試是否爲Set中的元素:

>>> x = {'foo', 'bar', 'baz'}
>>> len(x)
3

>>> 'bar' in x
True
>>> 'qux' in x
False

Set基本操做

方法和運算符

許多可用於Python其餘數據類型的操做對集合沒有意義。例如,沒法對集合創建索引或切片。可是,Python在set對象上提供了運算符,這些操做符其實不少和數學裏是如出一轍的,相信數學好的朋友們對這部分簡直不要太熟悉

因此對於Set的操做除了用普通的內置方法,咱們也可使用運算符,比較方便

Union 並集
  • 用法:計算兩個或更多集合的並集。
  • 方法: x1.union(x2[, x3 ...])
  • 運算符:x1 | x2 [| x3 ...]

讓咱們新建兩個Set作測試:

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

如今咱們想求x1,x2的並集,以下圖所示:

clipboard.png

具體實現方法以下,或是用方法,或是用操做符:

>>> 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 交集
  • 方法: x1.intersection(x2[, x3 ...])
  • 運算符:x1 & x2 [& x3 ...]
  • 用法:計算兩個或更多集合的交集。

如今還讓咱們用剛纔建立好的兩個set,所求部分以下圖:

clipboard.png

實現仍然是兩種方法:

>>> 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[, x3 ...])
  • 運算符:x1 - x2 [- x3 ...]
  • 用法:計算兩個或更多集合的差集。大白話說就是x1去除x1和x2的共有元素

下圖所示爲x1.difference(x2)的目標結果:
clipboard.png

>>> 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},具體流程以下圖所示:

clipboard.png

Symmetric Difference 對稱差集
  • 方法: x1.symmetric_difference(x2)
  • 運算符:x1 ^ x2 1
  • 用法:計算兩個或更多集合的差集。大白話說就是x1去除x1和x2的共有元素

下圖所示爲x1.symmetric_difference(x2)的目標結果:

clipboard.png

實現方法以下;

>>> 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.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.issubset(x2)
  • 運算符:x1 <= x2
  • 用法:若是返回True,x1爲x2子集,反之返回False
>>> 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的真子集,若是返回True,x1爲x2的真子集,反之返回False

首先。。。讓咱們回顧一下數學知識:真子集與子集相似,除了集合不能相同。若是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.issuperset(x2)
  • 運算符:x1 >= x2
  • 用法:判斷x1是否爲x2的超集,若是是返回True,反之返回False
>>> 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的真超集,若是是返回True,反之返回False

真超集與超集相同,除了集合不能相同。若是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

對Set進行修改

雖然集合中包含的元素必須是不可變類型,但能夠修改集合自己。與上面的操做相似,可使用多種運算符和方法來更改集合的內容。

x1.update(x2) 經過union修改集合元素
  • 方法:x1.update(x2[, x3 ...])
  • 運算符:x1 |= x2 [| x3 ...]
  • 用法:經過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[, x3 ...])
  • 運算符:x1 &= x2 [& x3 ...]
  • 用法:經過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[, x3 ...])
  • 運算符:x1 -= x2 [| x3 ...]
  • 用法:經過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.symmetric_difference_update(x2)
  • 運算符:x1 ^= 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

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詳解介紹能夠幫助到你們,若是幫到了你,就點個贊吧~~
最後再次祝你們豬年大吉!!


  1. x3 ...
相關文章
相關標籤/搜索