Python set 和 frozenset 常用來表示一群不重複 element 的集合,這篇文章就來介紹一下 Python set 和 frozenset。
Table of Contents
1. 特性
1.1 set, frozenset 的共通特性
- object 內的 element 不會重複
- 沒有順序性
1.2 set, frozenset 的差別
set 和 frozenset 的差別其實就像 list 和 tuple 一樣,set 是 mutable,frozenset 是 immutable,宣告後就不能對其做其他操作。
my_set = set(range(3))
my_set.add(5)
print(my_set)
{0, 1, 2, 5}
my_frozenset = frozenset(range(3))
my_frozenset.add(5)
AttributeError: 'frozenset' object has no attribute 'add'
2. 宣告
2.1 宣告 set
2.1.1 braces: {}
如果要宣告有 elements 的 set 的話,可以用大括號把 elements 包在裡面,但如果要宣告的 set 是空的話,就需要用 set type constructor,否則會變成 dict。
my_set = {1, 1, 2, 2, 3, 3}
print(type(my_set))
<class 'set'>
# set 會自動把重複項目刪除
print(my_set)
{1, 2, 3}
empty_dict = {}
print(type(empty_dict))
<class 'dict'>
print(empty_dict)
{}
empty_set = set()
print(type(empty_set))
<class 'set'>
print(empty_set)
set()
2.1.2 Set Comprehension
Comprehension 是 Python 中特殊的表示法,詳細介紹可以參考:Python Comprehension 語法 – List Comprehension, Set Comprehension, Dict Comprehension。
Set Comprehension 的語法:
{expression for item in iterable (if condition)}
至於 iterable 的定義,可以參考這篇:Python Iterable Objects 介紹
my_set = {i for i in range(5)}
print(type(my_set))
<class 'set'>
print(my_set)
{0, 1, 2, 3, 4}
my_set = {i * 2 for i in range(5)}
print(my_set)
{0, 2, 4, 6, 8}
my_set = {s for s in 'Hello World'}
print(my_set)
{'e', 'H', 'W', 'o', 'r', ' ', 'd', 'l'}
2.1.3 type constructor: set()
可以用 set 的 type constructor 來宣告 set
class set([iterable])
可將 iterable object 轉換成 set,但 iterable object 的每個 item 都必須是 hashable object,否則無法轉成 set:
An object is hashable if it has a hash value which never changes during its lifetime (it needs a__hash__()
method), and can be compared to other objects (it needs an__eq__()
method). 資料來源:Python document
my_str = 'hi'
print(set(my_str))
{'h', 'i'}
my_list = [1, 2]
print(set(my_list))
{1, 2}
my_tuple = (1, 2)
print(set(my_tuple))
{1, 2}
# set 不保證順序
my_dict = { 'name': 'jimmy', 'city': 'taipei' }
print(set(my_dict))
{'city', 'name'}
print(set(my_dict.values()))
{'taipei', 'jimmy'}
my_set = {1, 2}
print(set(my_set))
{1, 2}
my_list = [[1], [2]]
print(set(my_list))
TypeError: unhashable type: 'list'
2.2 宣告 frozenset – frozenset type constructor
宣告 frozenset 只有一種方法,就是用 frozenset 的 type constructor。
class frozenset([iterable])
和 set type constructor 一樣,iterable object 的每個 item 都必須是 hashable object,否則無法轉成 set
my_str = 'hi'
print(frozenset(my_str))
frozenset({'h', 'i'})
my_list = [1, 2]
print(frozenset(my_list))
frozenset({1, 2})
my_tuple = (1, 2)
print(frozenset(my_tuple))
frozenset({1, 2})
# frozenset 不保證順序
my_dict = { 'name': 'jimmy', 'city': 'taipei' }
print(frozenset(my_dict))
frozenset({'name', 'city'})
print(frozenset(my_dict.values()))
frozenset({'jimmy', 'taipei'})
my_frozenset = {1, 2}
print(frozenset(my_frozenset))
frozenset({1, 2})
my_list = [[1], [2]]
print(frozenset(my_list))
TypeError: unhashable type: 'list'
3. Common Operation
因為 set 和 frozenset 是無順序性的,所以每個 element 不會有 index,也不能用 slice 的方法取得 set 或 frozenset 的部分片段,只能判斷某 element 是否存在於 set 或 frozenset。
3.1 in
用來判斷某 element 是否存在 set 或 frozenset 中
my_set = {1, 3, 7}
print(3 in my_set)
True
print(5 in my_set)
False
my_frozenset = frozenset({1, 3, 7})
print(3 in my_frozenset)
True
print(5 in my_frozenset)
False
3.2 not in
跟 in 相反,用來判斷這個 element 是否不在 set 或 frozenset 裡:
my_set = {1, 3, 7}
print(3 not in my_set)
False
print(5 not in my_set)
True
my_frozenset = frozenset({1, 3, 7})
print(3 not in my_frozenset)
False
print(5 not in my_frozenset)
True
3.3 len()
用來回傳 set 或 frozenset 的長度
my_set = {1, 3, 7}
print(len(my_set))
3
my_frozenset = frozenset({1, 3, 7})
print(len(my_frozenset))
3
4. 操作 set
4.1 set.add(element)
將某 element 加到 set 裡面,如果該 element 已經在 set 裡,則自動忽略
my_set = {1, 3, 7}
my_set.add(9)
print(my_set)
{1, 3, 9, 7}
my_set.add(1)
print(my_set)
{1, 3, 9, 7}
4.2 set.remove(element)
移除 set 中的某個 element,如果該 element 本來就不在 set 裡,會 raise KeyError
my_set = {1, 3, 7}
my_set.remove(3)
print(my_set)
{1, 7}
my_set.remove(5)
KeyError: 5
4.3 set.discard(element)
移除 set 中的某個 element,和 remove 的差別在於,如果該 element 不在 set 的話,不會噴錯
my_set = {1, 3, 7}
my_set.discard(3)
print(my_set)
{1, 7}
my_set.discard(5)
print(my_set)
{1, 7}
4.4 set.pop()
pop 會隨機移除 set 的某個 element,如果該 set 是空的,會 raise KeyError
my_set = {1, 3, 7}
print(my_set.pop())
1
print(my_set)
{3, 7}
my_set = set()
print(my_set.pop())
KeyError: 'pop from an empty set'
4.5 set.clear()
清空 set 裡的所有 elements
my_set = {1, 3, 7}
my_set.clear()
print(my_set)
set()
5. 集合
set 還有一個很常的應用場景是用在數學的集合上
5.1 intersection – 交集
以下兩個語法都可以取到兩個 set 的交集,也就是兩個 set 都出現的 element
set_a.intersection(set_b) set_a & set_b
my_set_a = {1, 3, 6, 8, 10}
my_set_b = {1, 2, 6, 8}
print(my_set_a.intersection(my_set_b))
{8, 1, 6}
print(my_set_a & my_set_b)
{8, 1, 6}
5.2 union – 聯集
以下兩個語法都可以取到兩個 set 的聯集,也就是兩個 set 只要出現過一次的 element
set_a.union(set_b) set_a | set_b
my_set_a = {1, 3, 6, 8, 10}
my_set_b = {1, 2, 6, 8}
print(my_set_a.union(my_set_b))
{1, 2, 3, 6, 8, 10}
print(my_set_a | my_set_b)
{1, 2, 3, 6, 8, 10}
5.3 difference – 差集
以下兩個語法都可以取到 set_a 和 set_b 的差集,也就是 set_a 把 set_a 和 set_b 的交集刪除
set_a.difference(set_b) set_a - set_b
my_set_a = {1, 3, 6, 8, 10}
my_set_b = {1, 2, 6, 8}
print(my_set_a.difference(my_set_b))
{10, 3}
print(my_set_a - my_set_b)
{10, 3}
5.4 symmetric_difference – 對稱差集
以下兩個語法都可以取到 set_a 和 set_b 的對稱差集,也就是 set_a 和 set_b 的聯集把 set_a 和 set_b 的交集刪除
set_a.symmetric_difference(set_b) set_a ^ set_b
my_set_a = {1, 3, 6, 8, 10}
my_set_b = {1, 2, 6, 8}
print(my_set_a.symmetric_difference(my_set_b))
{2, 3, 10}
print(my_set_a ^ my_set_b)
{2, 3, 10}
5.5 subset, superset
可以用 issubset 和 issuperset 來判斷兩個 set 是否互為 subset 或 superset
set_a.issubset(set_b) set_a <= set_b set_a.issuperset(set_b) set_a >= set_b
my_set_a = {1, 3, 6, 8}
my_set_b = {1, 3, 6}
print(my_set_a.issubset(my_set_b))
False
print(my_set_b.issubset(my_set_a))
True
print(my_set_a.issuperset(my_set_b))
True
print(my_set_b.issuperset(my_set_a))
False
參考資料
[Python] 學習使用集合(Set) – 通訊雜記
集合set – Python 教學| STEAM 教育學習網
Built-in Types — Python 3.11.5 documentation
如果覺得我的文章有幫助的話,歡迎幫我的粉專按讚哦~謝謝你!