Python 容器:Dict & Set
之前的文章中已經介紹了兩種集合類型:List (列表) 和 Tuple (元組)。它們都是有序的序列,但在可變性上有所不同。
今天,將繼續探討 Python 內置的另外兩種強大的集合類型:Dictionary (字典) 和 Set (集合)。這兩種類型在處理非序列化、需要快速查找的數據時尤其有用。本文將重點介紹 Dictionary,因為它在日常編程中極為常用,然後再簡要說明 Set 的概念和用法。
📕 字典 (Dictionary)
Dictionary (簡稱 dict) 是 Python 中一種非常靈活的數據結構。它不按順序存儲元素,而是以 鍵-值對 (key-value pair) 的形式存儲數據。你可以把它想像成一本真實世界的字典,每個「單詞」(key) 都對應一個「解釋」(value)。
Dictionary 和 List 一樣是可變的 (mutable),意味著你可以隨時新增、刪除或修改其中的元素。
創建一個 Dictionary
創建 Dictionary 非常簡單,主要使用大括號 {}。
# 創建一個空的 Dictionary
empty_dict = {}
# 或者使用 dict() 函數
empty_dict_alt = dict()
print(empty_dict) # Output: {}
print(type(empty_dict)) # Output: <class 'dict'>
# 創建一個帶有初始值的 Dictionary
student = {
"name": "Chan Tai Man",
"age": 20,
"major": "Computer Science",
"courses": ["CS101", "MATH203"]
}
print(student)
# Output: {'name': 'Chan Tai Man', 'age': 20, 'major': 'Computer Science', 'courses': ['CS101', 'MATH203']}Key 的重要規則:
Dictionary 的 key 必須是不可變的 (immutable)。這意味著你可以使用 int, str, float, bool 甚至是 tuple 作為 key,但不能使用 list 或其他 dict 作為 key。
# 合法的 key
valid_keys_dict = {
1: "Integer key",
"hello": "String key",
(1, 2): "Tuple key"
}
# 不合法的 key (會引發 TypeError)
# invalid_keys_dict = {
# [1, 2]: "List key" # TypeError: unhashable type: 'list'
# }通常,key 的大小相對較小,而它指向的 value 可能是一個較大的 Object,但這並非硬性規定。
關於順序,自 Python 3.7 版本起,Dictionary 會記住元素的插入順序。但在舊版本中,Dictionary 是無序的。因此,一個好的編程習慣是不要依賴 Dictionary 的順序來實現你的邏輯。
存取、新增和修改元素
Dictionary 的操作圍繞著它的 key 進行。
student = {"name": "Chan Tai Man", "age": 20}
# 1. 存取元素 (Accessing)
# 使用方括號 [],如果 key 不存在會引發 KeyError
print(student["name"]) # Output: Chan Tai Man
# 使用 get() 方法更安全,如果 key 不存在,可以返回一個預設值 (預設是 None)
print(student.get("age")) # Output: 20
print(student.get("gpa")) # Output: None
print(student.get("gpa", "N/A")) # Output: N/A
# 2. 新增或修改元素 (Adding / Modifying)
# 如果 key 已存在,則更新 value
student["age"] = 21
print(student) # Output: {'name': 'Chan Tai Man', 'age': 21}
# 如果 key 不存在,則新增一個 key-value pair
student["major"] = "Computer Science"
print(student) # Output: {'name': 'Chan Tai Man', 'age': 21, 'major': 'Computer Science'}移除元素
你可以使用 del 關鍵字或 pop() 方法來移除元素。
student = {"name": "Chan Tai Man", "age": 21, "major": "Computer Science"}
# 使用 del 關鍵字,如果 key 不存在會引發 KeyError
del student["major"]
print(student) # Output: {'name': 'Chan Tai Man', 'age': 21}
# 使用 pop() 方法,它會移除 key 並返回其 value
# 如果 key 不存在,可以提供一個預設值,否則會引發 KeyError
age = student.pop("age")
print(age) # Output: 21
print(student) # Output: {'name': 'Chan Tai Man'}
# popitem() 移除並返回最後插入的 (key, value) pair (Python 3.7+)
student = {"a": 1, "b": 2, "c": 3}
item = student.popitem()
print(item) # Output: ('c', 3)
print(student) # Output: {'a': 1, 'b': 2}
# clear() 清空整個 Dictionary
student.clear()
print(student) # Output: {}檢查 Key 或 Value 是否存在
檢查 key 的存在性非常高效,而檢查 value 則需要遍歷整個 dict。
student = {"name": "Chan Tai Man", "age": 21}
# 檢查 key 是否存在 (非常快)
print("name" in student) # Output: True
print("major" in student) # Output: False
# 檢查 value 是否存在 (較慢,需要遍歷)
print(21 in student.values()) # Output: True
print("Computer Science" in student.values()) # Output: False遍歷 Dictionary
最常用的遍歷方式是使用 for 循環和 items() 方法,它可以同時獲取 key 和 value。
student = {"name": "Chan Tai Man", "age": 21, "major": "Computer Science"}
# 1. 遍歷所有的 key (預設行為)
print("--- Keys ---")
for key in student:
print(key)
# 2. 遍歷所有的 value
print("\n--- Values ---")
for value in student.values():
print(value)
# 3. 遍歷所有的 key-value pair (最常用)
print("\n--- Items (Key-Value pairs) ---")
for key, value in student.items():
print(f"Key: {key}, Value: {value}")Dictionary 的核心優勢:快速查找
Dictionary 最重要的用途是根據 key 快速查找 value。它的類似 Hash Table,查找、新增和刪除操作都很快。
相反 List 在查找元素時需要從頭到尾去搜索。
應用場景: 當你需要存儲一些臨時結果以備後用,或作為一種快取時,Dictionary 非常有用。
例如,計算一個複雜的數學函數,你可以將計算結果存儲在 dict 中,key 是函數的輸入,value 是計算結果。下次用相同的輸入調用函數時,直接從 dict 中讀取結果,避免重複計算。
合併與複製
合併 Merging
你可以用 update() 方法或 | 操作符(Python 3.9+)來合併兩個 dict。
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
# 使用 update(),會修改 dict1
dict1_copy.update(dict2)
print(f"Updated dict1: {dict1_copy}") # Output: Updated dict1: {'a': 1, 'b': 3, 'c': 4}
# 使用 | 操作符 (Python 3.9+),會創建一個新的 dict
# 如果有重複的 key,後面的 dict 會覆蓋前面的
merged_dict = dict1 | dict2
print(f"Merged dict: {merged_dict}") # Output: Merged dict: {'a': 1, 'b': 3, 'c': 4}複製 Copying
複製 dict 時需要注意淺複製 (shallow copy) 和深複製 (deep copy) 的區別。
- 淺複製 (
copy()方法):創建一個新的dictObject,但如果value是可變類型(如list),它只會複製該value的引用,而不是value本身。 - 深複製 (
copy.deepcopy()):創建一個全新的dict,並遞歸地複製所有嵌套的 Object。
import copy
original_dict = {
'id': 1,
'data': ['A', 'B']
}
# 1. 淺複製 (新字典和舊字典的 key 指向同一 Object)
shallow_copied_dict = original_dict.copy()
shallow_copied_dict['data'].append('C')
print(f"Original after shallow copy: {original_dict}")
# Output: Original after shallow copy: {'id': 1, 'data': ['A', 'B', 'C']}
# 注意:原始字典的 data 也被修改了!
# 2. 深複製 (新字典和舊字典的 key 不會指向同一 Object)
original_dict = { # 重置
'id': 1,
'data': ['A', 'B']
}
deep_copied_dict = copy.deepcopy(original_dict)
deep_copied_dict['data'].append('C')
print(f"Original after deep copy: {original_dict}")
# Output: Original after deep copy: {'id': 1, 'data': ['A', 'B']}
# 原始字典保持不變Dictionary 常用方法總結
| 方法 (Method) | 描述 (Description) |
|---|---|
d.keys() | 返回一個包含所有 key 的視圖 Object。 |
d.values() | 返回一個包含所有 value 的視圖 Object。 |
d.items() | 返回一個包含所有 (key, value) pair 的視圖 Object。 |
d.get(key, def) | 根據 key 獲取 value,若 key 不存在則返回 def(預設為 None)。 |
d.pop(key, def) | 移除指定的 key 並返回其 value,若不存在則返回 def。 |
d.popitem() | 移除並返回最後插入的 (key, value) pair。 |
d.update(other_d) | 用另一個 dict 的 key-value pair 來更新當前的 dict。 |
d.clear() | 清空 dict 中的所有元素。 |
d.copy() | 返回 dict 的一個淺複製。 |
🧩 集合 (Set)
Set (集合) 是另一個非常有用的數據結構。它的特點是:
- 無序 (Unordered):元素沒有固定的順序。
- 唯一 (Unique):不允許包含重複的元素。
- 可變 (Mutable):可以新增或刪除元素。
Set 不常用,但在需要處理唯一性或進行數學集合運算時,便會用到。
創建一個 Set
你可以用大括號 {} 或 set() 函數來創建 set。
# 使用大括號創建 set
# 注意: {} 中沒有冒號,不是字典,沒有 k/v 對
fruits = {"apple", "banana", "orange", "apple"} # 重複的 "apple" 會被自動忽略
print(fruits) # Output: {'orange', 'apple', 'banana'} (順序可能不同)
# 使用 set() 函數從 list 創建 set
numbers_list = [1, 2, 3, 2, 1, 4]
unique_numbers = set(numbers_list)
print(unique_numbers) # Output: {1, 2, 3, 4}
# 重要:創建一個空的 set 必須使用 set()
empty_set = set()
# empty_dict = {} # 這會創建一個空的 dictionary!基本操作
Set 的基本操作和 Dictionary 有些相似,但它沒有 key。
s = {1, 2, 3}
# 獲取長度
print(len(s)) # Output: 3
# 檢查成員資格 (非常快)
print(2 in s) # Output: True
print(5 in s) # Output: False
# 新增元素
s.add(4)
s.add(2) # 再次新增 2 不會有任何效果
print(s) # Output: {1, 2, 3, 4}
# 移除元素
s.remove(3) # 元素不存在會有 KeyError
print(s) # Output: {1, 2, 4}
s.discard(5) # 元素不存在也不會錯誤,比較安全
print(s) # Output: {1, 2, 4}數學集合運算
Set 最強大的功能是它支持高效的集合運算。
| 操作 (Operation) | 運算符 (Operator) | 方法 (Method) | 描述 (Description) |
|---|---|---|---|
| 聯集 (Union) | a | b | a.union(b) | 返回包含 a 和 b 所有元素的新集合 |
| 交集 (Intersection) | a & b | a.intersection(b) | 返回 a 和 b 的共有元素的新集合 |
| 差集 (Difference) | a - b | a.difference(b) | 返回在 a 中但不在 b 中的元素 |
| 對稱差集 (Symmetric Difference) | a ^ b | a.symmetric_difference(b) | 返回只在 a 或 b 其中之一的元素 |
set_a = {1, 2, 3, 4}
set_b = {3, 4, 5, 6}
# 聯集
print(f"Union: {set_a | set_b}") # Output: {1, 2, 3, 4, 5, 6}
# 交集
print(f"Intersection: {set_a & set_b}") # Output: {3, 4}
# 差集 (在 A 但不在 B)
print(f"Difference (A - B): {set_a - set_b}") # Output: {1, 2}
# 對稱差集 (只在其中一個集合的元素)
print(f"Symmetric Difference: {set_a ^ set_b}") # Output: {1, 2, 5, 6}🤔 Dictionary vs Set:如何選擇?
了解了 dict 和 set 後,你可能會問,在什麼情況下應該用哪一個?
使用
Dictionary當你:- 需要將數據(
value)與一個唯一的標識符(key)關聯起來。 - 數據是成對出現的,例如:用戶名對應用戶資料、配置項名稱對應配置值。
- 需要基於
key進行快速查找、更新或刪除操作。
- 需要將數據(
使用
Set當你:- 只需要存儲一堆唯一的項目,而不需要關聯任何其他數據。
- 最主要的操作是檢查一個項目是否存在於集合中。
- 需要執行去重操作或集合運算(如聯集、交集)。
簡單來說:需要 key-value 結構,用 dict;只需要唯一的 value,用 set。
📝 總結
Dictionary 和 Set 是 Python 中處理非序列化數據的兩大利器。Dictionary 以其高效的 key-value 查找能力,成為了程序員工具箱中最常用的數據結構之一。而 Set 則在處理唯一性和集合運算方面表現出色。
掌握這四種基本的集合類型 (List, Tuple, Dictionary, Set),並理解它們各自的優缺點和適用場景,是成為一個高效 Python 開發者的關鍵一步。希望這篇文章能幫助你更好地理解和運用它們!