Python Set 集合是以大括號 {} 建立的無序容器,最大的特點是自動去除重複元素,確保每個值只出現一次。本文全攻略 Set 的建立語法、add、remove、discard 等常用方法、集合運算(聯集、交集、差集、對稱差),以及 frozenset 不可變集合、Set Comprehension 生成式與實戰去重應用,讓你徹底掌握 Python Set 的核心技巧。
什麼是 Set 集合?
Set(集合)是 Python 的內建資料型別,使用大括號 {} 建立,元素之間以逗號分隔。它有兩個核心特性:無序(unordered)與唯一性(unique)——Set 不保留元素的插入順序,也不允許重複值,加入已存在的元素時會自動忽略。
可以把 Set 想像成一個只收「不重複票」的票箱:你投入再多同樣的票,箱子裡也只保留一張。這讓 Set 天生適合做去重(deduplication)、成員測試(membership test),以及數學集合運算如聯集、交集、差集。
Set 的成員測試速度比 List 快許多(底層使用雜湊表),因此當你需要頻繁執行 x in collection 的查詢時,Set 是比 List 更好的選擇。
核心語法:建立與基本操作
# === 建立 Set ===
# 方式一:大括號,元素直接列出
fruits = {'apple', 'banana', 'orange', 'apple'} # 重複的 apple 自動去除
print(fruits) # {'apple', 'banana', 'orange'}(順序不保證)
# 方式二:set() 轉換其他序列(最常用的去重技巧)
nums_with_dup = [1, 2, 2, 3, 3, 3, 4]
unique_nums = set(nums_with_dup)
print(unique_nums) # {1, 2, 3, 4}
# 建立空 Set(注意:{} 是空 Dict,不是空 Set!)
empty_set = set() # ✅ 正確
wrong = {} # ❌ 這是空字典,不是空集合
print(type(empty_set)) #
print(type(wrong)) #
建立空 Set 必須用set(),不能用{}。{}在 Python 中代表空字典(dict),這是初學者最常踩的陷阱。
# === 新增與刪除元素 ===
tickers = {'AAPL', 'TSLA', 'GOOGL'}
# add():新增單一元素(重複加入不報錯,靜默忽略)
tickers.add('MSFT')
tickers.add('AAPL') # AAPL 已存在,Set 不變
print(tickers) # {'AAPL', 'TSLA', 'GOOGL', 'MSFT'}
# remove():刪除元素,若不存在則拋出 KeyError
tickers.remove('TSLA')
# discard():刪除元素,不存在時靜默忽略(更安全)
tickers.discard('NVDA') # NVDA 不在集合中,不報錯
# pop():隨機移除並回傳一個元素(因為 Set 無順序)
removed = tickers.pop()
print(f'移除了:{removed}')
# clear():清空整個 Set
tickers.clear()
print(tickers) # set()
日常使用建議優先選discard()而非remove()——前者在元素不存在時安靜忽略,程式不會崩潰;後者若 Key 不存在會拋出KeyError。
# === 成員測試與長度 ===
watchlist = {'AAPL', 'TSLA', 'GOOGL', 'MSFT'}
print('AAPL' in watchlist) # True
print('NVDA' in watchlist) # False
print('NVDA' not in watchlist) # True
print(len(watchlist)) # 4
規則與注意事項
| 規則 | 正確範例 | 錯誤範例 |
|---|---|---|
| Set 元素必須可雜湊(hashable) | {1, 'hello', (1, 2)} |
{[1, 2], 3} → TypeError |
| 建立空 Set 用 set(),不用 {} | s = set() |
s = {}(這是空 Dict) |
| Set 無索引,不支援 s[0] 存取 | for item in s:(迭代) |
s[0] → TypeError |
| 重複元素自動忽略,不報錯 | s.add('已存在的值')(靜默) |
誤以為 add 重複值會拋例外 |
| discard 比 remove 更安全 | s.discard('不存在的值') |
s.remove('不存在的值') → KeyError |
常見錯誤與防呆
錯誤一:用 {} 建立空 Set
# ❌ 錯誤寫法(這是空字典,不是空集合)
s = {}
print(type(s)) #
# ✅ 正確寫法
s = set()
print(type(s)) #
錯誤二:把 List 放入 Set(List 不可雜湊)
# ❌ 錯誤寫法(TypeError: unhashable type: 'list')
s = {[1, 2], [3, 4]}
# ✅ 正確寫法:List 改用 Tuple 作為集合元素
s = {(1, 2), (3, 4)}
print(s) # {(1, 2), (3, 4)}
錯誤三:試圖用索引存取 Set 元素
# ❌ 錯誤寫法(TypeError: 'set' object is not subscriptable)
s = {10, 20, 30}
print(s[0])
# ✅ 正確做法:用 for 迭代,或先轉為 List 再取索引
for item in s:
print(item)
# 或轉成 list 再取值(注意順序不保證)
s_list = list(s)
print(s_list[0])
進階用法
集合運算:聯集、交集、差集、對稱差
Set 最強大的地方在於支援數學意義上的集合運算,讓資料比較工作只需一行程式碼即可完成。
A = {'AAPL', 'TSLA', 'GOOGL', 'MSFT'} # 自選股A
B = {'TSLA', 'MSFT', 'NVDA', 'META'} # 自選股B
# 聯集(union):兩個集合所有不重複元素
print(A | B) # {'AAPL', 'TSLA', 'GOOGL', 'MSFT', 'NVDA', 'META'}
print(A.union(B)) # 同上
# 交集(intersection):兩個集合共有的元素
print(A & B) # {'TSLA', 'MSFT'}
print(A.intersection(B)) # 同上
# 差集(difference):在 A 中但不在 B 中的元素
print(A - B) # {'AAPL', 'GOOGL'}
print(A.difference(B)) # 同上
# 對稱差(symmetric_difference):只在其中一個集合的元素
print(A ^ B) # {'AAPL', 'GOOGL', 'NVDA', 'META'}
print(A.symmetric_difference(B)) # 同上
快速去重:List 轉 Set 再轉回
最常見的 Set 使用場景:將含有重複項目的 List 去重,保留唯一值。這個技巧只需一行,且效能遠優於手動用 for 迴圈判斷。
# 情境:量化回測中,過濾重複的交易信號日期
trade_dates = ['2024-01-03', '2024-01-05', '2024-01-03',
'2024-01-08', '2024-01-05', '2024-01-10']
unique_dates = list(set(trade_dates)) # 去重後轉回 List
unique_dates.sort() # Set 無序,需手動排序
print(unique_dates)
# ['2024-01-03', '2024-01-05', '2024-01-08', '2024-01-10']
# 快速確認是否有重複
has_dup = len(trade_dates) != len(set(trade_dates))
print(f'有重複?{has_dup}') # 有重複?True
Set Comprehension 集合生成式
與 List Comprehension 語法相似,Set Comprehension 使用大括號,一行建立含有特定條件的集合,並自動去除重複。
# 取 1~20 中所有偶數,並自動去重
even_set = {x for x in range(1, 21) if x % 2 == 0}
print(even_set) # {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}
# 取字串中所有不重複的字母(自動小寫化)
sentence = 'Python is Fun'
unique_chars = {c.lower() for c in sentence if c != ' '}
print(unique_chars) # {'p', 'y', 't', 'h', 'o', 'n', 'i', 's', 'f', 'u'}
煉金坊小叮嚀
Set 是四大基礎資料結構中最容易被忽略,卻在特定場景極為好用的一個!我在量化交易開發中,最常用它來過濾重複的信號、快速比對兩個觀察名單的差異。記住一個選用法則:需要去重或快速成員查詢,用 Set;需要保留順序或索引存取,用 List。 另外,別忘了空集合只能用 set() 建立,{} 是字典,這個細節很多人寫了很久還是會搞混。Set 的集合運算(&、|、-)更是資料比對的神器,一行程式碼就能完成以前需要雙層迴圈才能做到的事。