文章目錄
- 核心特點
- 基本語法
- 常見使用場景
- 1. 分組數據(默認值為列表)
- 2. 計數(默認值為整數)
- 3. 集合操作(默認值為集合)
- 4. 嵌套字典
- 注意事項
- 與普通字典對比
- 總結
- 1. 鍵(Key)的類型
- 2. 值(Value)的類型
- 3. `default_factory` 的返回值
- 4. 嵌套 `defaultdict` 的鍵值
- 5. 鍵和值的可變性總結
- 常見問題解答
- Q1:可以用 `list` 作為鍵嗎?
- Q2:可以用 `defaultdict` 作為鍵嗎?
- Q3:值可以是函數或類嗎?
- 總結
在 Python 中,
defaultdict
是
collections
模塊提供的一個非常有用的類,它是內置字典類型
dict
的子類。
defaultdict
的主要特點是
自動處理字典中不存在的鍵,避免在使用普通字典時因訪問不存在的鍵而拋出
KeyError
異常。
核心特點
- 自動初始化默認值:當訪問一個不存在的鍵時,
defaultdict
會調用指定的默認工廠函數(default_factory
)生成一個初始值,確定了字典中值的類型。 - 簡化代碼:無需手動檢查鍵是否存在,適合需要分組、統計或聚合數據的場景。
基本語法
from collections import defaultdictd = defaultdict(default_factory)
default_factory
:一個可調用對象(如list
,int
,set
,str
或自定義函數),用于生成默認值。
常見使用場景
1. 分組數據(默認值為列表)
將數據按鍵分組,類似 SQL 的 GROUP BY
:
from collections import defaultdictdata = [("apple", "fruit"), ("carrot", "vegetable"), ("apple", "fruit")]
grouped = defaultdict(list)for name, category in data:grouped[category].append(name)print(grouped)
# 輸出:defaultdict(<class 'list'>, {'fruit': ['apple', 'apple'], 'vegetable': ['carrot']})
2. 計數(默認值為整數)
統計元素出現次數:
from collections import defaultdicttext = "apple banana apple orange banana"
words = text.split()
count = defaultdict(int)for word in words:count[word] += 1print(count)
# 輸出:defaultdict(<class 'int'>, {'apple': 2, 'banana': 2, 'orange': 1})
3. 集合操作(默認值為集合)
避免重復值:
from collections import defaultdictpairs = [("a", 1), ("b", 2), ("a", 3)]
unique = defaultdict(set)for key, value in pairs:unique[key].add(value)print(unique)
# 輸出:defaultdict(<class 'set'>, {'a': {1, 3}, 'b': {2}})
4. 嵌套字典
構建多層嵌套結構:
from collections import defaultdictnested = defaultdict(lambda: defaultdict(int))
nested["fruit"]["apple"] += 1
nested["vegetable"]["carrot"] += 2print(nested["fruit"]) # 輸出:defaultdict(<class 'int'>, {'apple': 1})
print(nested["unknown_key"]) # 輸出:defaultdict(<class 'int'>, {})
注意事項
default_factory
必須可調用:例如list
、int
是類(構造函數),而list()
或int()
的返回值不可作為工廠。- 僅對
d[key]
有效:使用d.get(key)
或key in d
不會觸發默認值生成。 - 性能:與普通字典性能接近,適合高頻插入操作。
與普通字典對比
# 普通字典需要手動處理缺失鍵
d = {}
key = "unknown"
if key not in d:d[key] = []
d[key].append(1)# defaultdict 自動處理
d = defaultdict(list)
d["unknown"].append(1)
總結
defaultdict
簡化了需要初始化默認值的字典操作,特別適合數據聚合、分組和統計場景。通過合理選擇 default_factory
(如 list
、int
、set
或自定義函數),可以大幅提升代碼簡潔性和可讀性。
在 Python 中,defaultdict
繼承自 dict
,因此它的 鍵(Key)和值(Value)的類型規則與普通字典一致,但也有一些細節需要注意。以下是詳細說明:
1. 鍵(Key)的類型
-
規則:鍵必須是 不可變類型(Immutable) 且 可哈希(Hashable)。
-
允許的類型:
- 基本類型:
int
,float
,str
,bool
,None
- 不可變容器:
tuple
(但元組內的元素也必須不可變) frozenset
(不可變集合)- 用戶自定義的不可變對象(需正確實現
__hash__
和__eq__
方法)。
- 基本類型:
-
禁止的類型:
- 可變類型:
list
,dict
,set
- 包含可變元素的
tuple
(例如(1, [2, 3])
)。
- 可變類型:
-
示例:
from collections import defaultdict# 合法鍵 d = defaultdict(int) d["apple"] = 10 # 字符串作為鍵 ? d[123] = 20 # 整數作為鍵 ? d[(1, 2)] = 30 # 不可變元組作為鍵 ?# 非法鍵(會拋出 TypeError) d[[1, 2]] = 40 # 列表不可哈希 ? d[{"a": 1}] = 50 # 字典不可哈希 ?
2. 值(Value)的類型
-
規則:值可以是 任意類型,包括可變對象。
-
允許的類型:
- 基本類型(
int
,float
,str
等) - 可變容器(
list
,dict
,set
) - 自定義對象、函數、類實例等。
- 基本類型(
-
示例:
from collections import defaultdict# 值可以是列表(可變) d_list = defaultdict(list) d_list["fruits"].append("apple")# 值可以是字典(可變) d_dict = defaultdict(dict) d_dict["data"]["count"] = 10# 值可以是自定義對象 class MyClass:passd_obj = defaultdict(MyClass) obj = d_obj["instance"] # 自動生成一個 MyClass 實例
3. default_factory
的返回值
default_factory
是一個可調用對象(如 list
, int
或自定義函數),它決定了 當鍵不存在時,默認值的類型。例如:
defaultdict(list)
:默認值是一個空列表([]
)。defaultdict(int)
:默認值是0
。defaultdict(lambda: "unknown")
:默認值是字符串"unknown"
。
值的類型完全由 default_factory
決定,與鍵的類型無關。
4. 嵌套 defaultdict
的鍵值
可以創建多層嵌套的 defaultdict
,鍵的規則依然適用:
from collections import defaultdict# 嵌套 defaultdict(值類型是另一個 defaultdict)
nested = defaultdict(lambda: defaultdict(int))# 合法操作
nested["fruit"]["apple"] += 1 # 鍵為 "fruit"(字符串)和 "apple"(字符串)
nested[123][(4, 5)] = 2 # 鍵為 123(整數)和 (4, 5)(不可變元組)# 非法操作(內層鍵非法)
nested["data"][[1, 2]] = 3 # 內層鍵為列表,不可哈希 ?
5. 鍵和值的可變性總結
特性 | 鍵(Key) | 值(Value) |
---|---|---|
類型限制 | 必須不可變且可哈希 | 可以是任意類型 |
可變性 | 不可變 | 可以可變 |
示例 | int , str , tuple | list , dict , 自定義對象 |
常見問題解答
Q1:可以用 list
作為鍵嗎?
- 否。列表是可變類型,不可哈希。若需用類似列表的結構作為鍵,可以轉換為不可變的
tuple
。
Q2:可以用 defaultdict
作為鍵嗎?
- 否。
defaultdict
是可變對象,不可哈希。只有不可變類型(如frozenset
)可以作為鍵。
Q3:值可以是函數或類嗎?
- 是。例如:
d = defaultdict(type) # 默認值是類對象 d["my_class"] = MyClass
總結
- 鍵:必須為不可變且可哈希的類型(如
str
,int
,tuple
)。 - 值:可以是任意類型(包括可變對象),具體由
default_factory
決定。 - 嵌套結構:可以自由嵌套
defaultdict
,但需確保每一層的鍵合法。