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()
方法):創建一個新的dict
Object,但如果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 開發者的關鍵一步。希望這篇文章能幫助你更好地理解和運用它們!