Python入門:集合set詳解

公衆號:尤而小屋
作者:Peter
編輯:Peter

大家好,我是Peter~

在前面的幾篇Python的文章中,我們介紹了Python的多種不同類型的對象:字符串、列表、元組、字典。它們有各自的特點:

  • 字符串str:存在索引,字符串中的元素是可以重複的,元素是不可變,不能修改的
  • 列表list:也能夠進行索引和切片操作,元素可以修改,是可變的
  • 元組tuple:可以看成是不能進行修改的“列表”;元素不能直接修改,也可以進行索引和切片操作,類似列表
  • 字典:Python中十分常用,鍵值對組成,鍵必須是比可變的數據類型(比如元組),值可以是任意數據;字典是無序的

如果說元組是列表和字符串的雜合體,那麼集合可以看做是列表和字典的雜合體

Python連載文章

Python入門的連載文章:

本文的整體目錄結構:

集合創建

集合set的創建有兩種方法:

  1. 通過set函數創建,空集合只能用這種方式
  2. 通過{}來創建

空集合

s1 = set()  # 空集合
s1
set()
type(s1)
set

注意:空集合必須使用set函數來創建,因爲{}是用來創建空字典的

非空集合

使用花括號創建

s2 = {1,2,3,4}  
s2
{1, 2, 3, 4}
type(s2)
set

使用set函數創建

s3 = set([9,8,7,6])  # 將元素用列表裝起來,set只能有一個參數
s3
{6, 7, 8, 9}
type(s3)
set
s4 = set((11,22,33,44))  # 用元組裝起來
s4
{11, 22, 33, 44}

集合的元素不能重複

集合中的元素是不能重複的;如果有重複的元素,集合會自動去重。這是一種非常高效的去重方式

s5 = set([1, 2, 3, 4, 3, 2, 1])  # 存在重複數據
s5
{1, 2, 3, 4}

產生的數據中自動將重複的去掉了

type(s5) # 查看類型
set
s6 = set("javascript") # 字符串中a重複了,自動去重
s6
{'a', 'c', 'i', 'j', 'p', 'r', 's', 't', 'v'}

特別點

當我們創建集合的時候,需要注意數據類型

s7 = {"python", [1,2,3,"java"], {"name":"xiaoming","age":19},100}
s7
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-11-b8ed1637ec12> in <module>
----> 1 s7 = {"python", [1,2,3,"java"], {"name":"xiaoming","age":19},100}
      2 s7


TypeError: unhashable type: 'list'

上面報錯中的關鍵詞:unhashable,中文是不可哈希的。意思是創建的時候存在不可哈希的數據類型:列表
。我們可以記住:

  • 不可哈希,即代表可變,比如列表、字典等
  • 可哈希,即代表不可變,比如字符串,字典的鍵等

當我們創建集合的時候,元素必須值可哈希的

set集合方法

首先我們通過dir(set)來查看集合的操作方法:

print(dir(set))
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']

add-添加不可變元素

集合中添加元素

s3  # 原集合
{6, 7, 8, 9}
s3.add(1)  # 添加1
s3
{1, 6, 7, 8, 9}
s3.add(2)  # 添加2
s3
{1, 2, 6, 7, 8, 9}
s3.add([1,3,5])
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-18-4efde33c70d1> in <module>
----> 1 s3.add([1,3,5])


TypeError: unhashable type: 'list'

報錯提示:列表是不可哈希,也就是可變類型的。之前我們說過:集合中的元素都是可哈希(不可變類型),所以不能直接添加

list1 = [1,3,5]
tuple1 = tuple(list1)  # 列表轉成元組,元組是不可變的

tuple1
(1, 3, 5)
s3.add(tuple1)  # 添加元組
s3
{(1, 3, 5), 1, 2, 6, 7, 8, 9}

update-更新集合

更新集合中的元素,將兩個集合中的元素組合在一起

# 創建兩個集合,有相同的元素“python”

s8 = set(["python","java","c"])
s9 = set(["python","go","javascript","html"])
s8.update(s9)
s8  
{'c', 'go', 'html', 'java', 'javascript', 'python'}

生成的數據中自動將python去重了

s9  # s9還是沒有變化的
{'go', 'html', 'javascript', 'python'}

update的參數不僅僅是集合,它的參數是不可變數據類型:

help(set.update)  # 查看方法的文檔信息
Help on method_descriptor:

update(...)
    Update a set with the union of itself and others.
s9.update("hello")
s9
{'e', 'go', 'h', 'html', 'javascript', 'l', 'o', 'python'}
s9.update((7,8,9))
s9
{7, 8, 9, 'e', 'go', 'h', 'html', 'javascript', 'l', 'o', 'python'}

pop-隨機刪除

隨機刪除一個元素,並且返回刪除的結果。pop不能指定參數,也就是不能指定想要刪除的元素

s9.pop()
'python'
s9.pop()
'html'
s9.pop("python")  # 不能帶參數
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-33-5037b93f4a38> in <module>
----> 1 s9.pop("python")  # 不能帶參數


TypeError: pop() takes no arguments (1 given)

remove-指定刪除

刪除的元素必須在集合中。如果不存在,則會報錯

s8
{'c', 'go', 'html', 'java', 'javascript', 'python'}
s8.remove("go")
s8  # 結果顯示go被刪除了
{'c', 'html', 'java', 'javascript', 'python'}
s8.remove("go")   # 再次刪除go就會報錯,因爲go已經不存在了
---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)

<ipython-input-37-88eafb5b8e9d> in <module>
----> 1 s8.remove("go")   # 再次刪除go就會報錯,因爲go已經不存在了


KeyError: 'go'

discard-指定刪除

指定刪除某個元素,如果元素不存在,也不會報錯。

s8  # 原數據
{'c', 'html', 'java', 'javascript', 'python'}
s8.discard("html")
s8  # 刪除後的數據
{'c', 'java', 'javascript', 'python'}
s8
{'c', 'java', 'javascript', 'python'}
s8.discard("go")

上面的結果表明:如果刪除的元素不存在,也不會報錯。這個是和remove不一樣的地方

clear-清空集合

刪除集合中的全部元素

s8
{'c', 'java', 'javascript', 'python'}
s8.clear()  # 清空了集合
s8
set()
bool(s8)  # bool值爲False
False

不變的集合-frozenset()

上面通過set方法創建的集合,我們瞭解到:集合是可變的,也就是可修改的,或者說不可哈希的。

實際上還有一種方式創建的集合是不可變的:frozenset(),可以理解成凍集合,所以就不能進行修改等操作啦。

f_set = frozenset("python")
f_set
frozenset({'h', 'n', 'o', 'p', 't', 'y'})

我們查看下這個凍集合的操作方法

print(dir(f_set))  # 凍集合
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'copy', 'difference', 'intersection', 'isdisjoint', 'issubset', 'issuperset', 'symmetric_difference', 'union']
print(dir(s9))  # set集合,非凍集合
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']

通過對比兩種集合的操作方法,我們發現:凍集合中明顯是少了很多增加、刪除等方法,所以凍集合是不可變的

集合運算

在這個小節中介紹的是集合中的各種運算,比如:交集、並集、補集等

in-元素判斷

s5
{1, 2, 3, 4}
1 in s5
True
6 in s5
False

issubset-子集與issuperset-超集

A如果是B的子集,那麼B就是A的超集;也就說A的元素全部在B中

s10 = {1,2}  # 創建一個新的集合
s10
{1, 2}
s10.issubset(s5)  # s10是s5的子集
True
s5.issuperset(s10)  #  s5是s10的超集
True
s9
{7, 8, 9, 'e', 'go', 'h', 'javascript', 'l', 'o'}
s9.issubset(s5)  # 很顯然s9不是s5的子集
False

intersection-交集

求兩個集合的交集,使用intersection函數或者&

print(s5)
print(s10)
{1, 2, 3, 4}
{1, 2}
s5.intersection(s10)
{1, 2}
s5 & s10
{1, 2}

union-並集

使用函數union或者|來表示兩個集合的並集,會生成一個新的對象

print(s5)
print(s9)
{1, 2, 3, 4}
{'javascript', 'o', 7, 'l', 'go', 'h', 8, 9, 'e'}
s11 = s5|s9
s11
{1, 2, 3, 4, 7, 8, 9, 'e', 'go', 'h', 'javascript', 'l', 'o'}
s5.union(s9)
{1, 2, 3, 4, 7, 8, 9, 'e', 'go', 'h', 'javascript', 'l', 'o'}

difference-差集、補集

使用函數difference或者減號-

print(s5)
print(s10)
{1, 2, 3, 4}
{1, 2}
s5 - s10
{3, 4}
s5.difference(s10)
{3, 4}
s10 - s5
set()

symmetric_difference-對稱差集

使用函數symmetric_difference或者symmetric_difference_update(原地更新數據)

s12 = {1,3,4,5,7}
s12
{1, 3, 4, 5, 7}
s5  # 原數據
{1, 2, 3, 4}
s5.symmetric_difference(s12)
{2, 5, 7}
s5  #  原數據沒有改變
{1, 2, 3, 4}
s5.symmetric_difference_update(s12) 
s5    # 原數據爲輸出結果
{2, 5, 7}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章