在撰寫 Python 程式時,我們經常會遇到一種情況:
「我們想把資料放進字典(Dictionary)裡,
但我們不確定這個 Key 到底存不存在。
如果不存在,我們需要先給它一個初始值。」
最常見的應用場景就是「分類資料」。
讓我們用一個非常簡單的教學例子來看看!
📝 情境:學生社團分類
假設我們有一份學生的報名資料,我們想把它整理成一個字典,
讓「社團名稱」變成 Key,而「參加的學生名單 (List)」變成 Value。
# 報名資料
records = [
("Alice", "吉他社"),
("Bob", "熱舞社"),
("Charlie", "吉他社"),
("David", "魔術社"),
("Eve", "熱舞社")
]❌ 寫法一:常見的新手寫法 (加上 if 判斷)
如果不用任何特殊語法,我們通常會這樣寫:
club_members = {}
for name, club in records:
# 1. 先檢查社團 (Key) 是否已經在字典裡
if club not in club_members:
# 2. 如果不在,就先建立一個空的列表
club_members[club] = []
# 3. 把學生名字加進列表裡
club_members[club].append(name)
print(club_members)
# 輸出: {'吉他社': ['Alice', 'Charlie'], '熱舞社': ['Bob', 'Eve'], '魔術社': ['David']}這段程式碼完全正確,
但為了「如果 Key 不存在就建立空列表」這件事,
我們多寫了兩行 if 判斷,稍微有點囉嗦。
✨ 寫法二:老練的寫法 (使用 setdefault)
這時候就是 setdefault 登場的最佳時機了!
同樣的邏輯,我們可以縮減成一行:
club_members = {}
for name, club in records:
# 核心魔法就在這一行:
club_members.setdefault(club, []).append(name)
print(club_members)
# 輸出一樣是: {'吉他社': ['Alice', 'Charlie'], '熱舞社': ['Bob', 'Eve'], '魔術社': ['David']}
🔍 拆解 setdefault 的運作原理
dictionary.setdefault(key, default_value) 這個函式在執行時,
其實偷偷幫你做了以下三件事:
尋找:檢查字典裡有沒有 club 這個 Key。
沒有的話就賦值:如果沒有這個 Key,
它會自動幫你在字典裡新增 club: [] (這裡的 [] 就是我們傳进去的預設值)。
回傳結果給我們操作:不管是原本就存在的 List,還是剛剛才建立的空 List,
它都會把這個 List 拋出來給我們。
因此,我們可以直接在後面接上 .append(name),把資料塞進去。
推薦hahow線上學習python: https://igrape.net/30afN
# Python `dict.setdefault()` 完整教學
很多 Python 初學者第一次看到 `dict.setdefault()` 都會疑惑:
> 「它到底是在設定什麼?為什麼還會有回傳值?」
其實,**`setdefault()` 的名稱並沒有完全表達它真正的行為**。
如果可以重新命名,我會覺得它比較像:
```python
dict.set_value_default()
```
也就是:
> **如果 key 不存在,就先設定一個預設 value,然後回傳該 value。**
換句話說,它做了兩件事:
1. 如果 key 不存在,建立 `key: default_value`
2. **回傳該 key 對應的 value**
因此可以把它想成下面這段程式:
```python
if key not in d:
d[key] = default_value
return d[key]
```
這樣理解,比只看 `setdefault` 這個名字更容易掌握它的用途。
---
# 基本語法
```python
value = d.setdefault(key, default_value)
```
如果 key 已存在:
* 不會修改原本的 value
* 回傳原本的 value
如果 key 不存在:
* 新增 key
* value 設為 `default_value`
* 回傳新的 value
---
# 範例一:key 不存在
```python
d = {}
v = d.setdefault("apple", 100)
print(d)
print(v)
```
輸出:
```python
{'apple': 100}
100
```
可以理解成:
```python
if "apple" not in d:
d["apple"] = 100
v = d["apple"]
```
---
# 範例二:key 已存在
```python
d = {
"apple": 50
}
v = d.setdefault("apple", 100)
print(d)
print(v)
```
輸出:
```python
{'apple': 50}
50
```
可以看到:
* 不會變成 100
* 回傳的是原本的 50
---
# 真正最常見的用途:建立 List
`setdefault()` 最常見的使用方式,不是設定整數,也不是字串。
而是:
> **default 幾乎都是空 List (`[]`)。**
例如,我們想依照水果種類分組。
沒有 `setdefault()`:
```python
d = {}
for fruit in ["apple", "banana", "apple", "orange", "banana"]:
if fruit not in d:
d[fruit] = []
d[fruit].append(fruit)
print(d)
```
結果:
```python
{
'apple': ['apple', 'apple'],
'banana': ['banana', 'banana'],
'orange': ['orange']
}
```
---
使用 `setdefault()`:
```python
d = {}
for fruit in ["apple", "banana", "apple", "orange", "banana"]:
d.setdefault(fruit, []).append(fruit)
print(d)
```
完全相同的結果:
```python
{
'apple': ['apple', 'apple'],
'banana': ['banana', 'banana'],
'orange': ['orange']
}
```
程式卻只剩一行。
---
# 為什麼可以直接 append?
因為:
```python
d.setdefault(fruit, [])
```
**回傳的是那個 List。**
所以:
第一次遇到 `"apple"`:
```python
d.setdefault("apple", [])
```
等同於:
```python
d["apple"] = []
return d["apple"]
```
因此:
```python
d.setdefault("apple", []).append("apple")
```
其實就是:
```python
d["apple"].append("apple")
```
第二次再遇到 `"apple"` 時:
```python
d.setdefault("apple", [])
```
發現 key 已存在。
因此:
* 不建立新的 List
* 直接回傳原本那個 List
所以:
```python
.append(...)
```
就會繼續加入原本的 List。
這也是為什麼:
```python
d.setdefault(key, []).append(value)
```
成了 Python 最經典的寫法之一。
---
# 心智模型
把它想成下面這個函式即可:
```python
def set_value_default(d, key, default_value):
if key not in d:
d[key] = default_value
return d[key]
```
所以:
```python
d.setdefault(key, [])
```
其實就是:
```python
set_value_default(d, key, [])
```
然後回傳:
```python
d[key]
```
---
# 重點整理
* `setdefault()` 的名字容易讓人誤會。
* 它真正的行為比較像 **`set_value_default()`**。
* 如果 key 不存在,就建立預設 value。
* **最後一定回傳該 key 的 value。**
* 最常見的用法是:
```python
d.setdefault(key, []).append(value)
```
* 因為回傳的是 List,所以可以直接接 `.append()`,省去判斷 key 是否存在的程式碼,讓程式更簡潔。
推薦hahow線上學習python: https://igrape.net/30afN
先補上一個很重要的觀念:setdefault() 適合偶爾建立預設值;如果整個字典都需要同一種預設值,通常 defaultdict 會更自然。
setdefault() vs defaultdict(list)
很多人在學會:
d.setdefault(key, []).append(value)
之後,就會接觸到另一種寫法:
from collections import defaultdict
d = defaultdict(list)
d[key].append(value)
兩者都能得到相同結果。
例如:
fruits = ["apple", "banana", "apple", "orange", "banana"]
使用 setdefault()
d = {}
for fruit in fruits:
d.setdefault(fruit, []).append(fruit)
print(d)
輸出:
{
'apple': ['apple', 'apple'],
'banana': ['banana', 'banana'],
'orange': ['orange']
}
使用 defaultdict(list)
from collections import defaultdict
d = defaultdict(list)
for fruit in fruits:
d[fruit].append(fruit)
print(dict(d))
輸出完全相同:
{
'apple': ['apple', 'apple'],
'banana': ['banana', 'banana'],
'orange': ['orange']
}
為什麼 defaultdict 可以不用 setdefault()?
因為:
d = defaultdict(list)
代表:
只要存取不存在的 key,就自動建立一個空 List。
因此:
d["apple"]
第一次存取時,Python 會自動做:
d["apple"] = []
所以接著就能直接:
d["apple"].append("apple")
不用自己判斷 key 是否存在。
兩者最大的差異
setdefault()
只有在你呼叫它時,才會建立預設值。
d.setdefault("apple", [])
意思是:
如果沒有
"apple",才建立它。
它屬於 dict 本身的方法。
defaultdict
是在建立字典時,就先告訴 Python:
未來所有不存在的 key,都請自動建立一個 List。
因此:
d[key]
就永遠不用擔心 KeyError。
什麼時候用哪一個?
使用 setdefault()
適合:
- 已經有一個普通 dict
- 只有少數地方需要建立預設值
- 不想改成
defaultdict
例如:
config.setdefault("timeout", 30)
或
groups.setdefault(name, []).append(student)
使用 defaultdict(list)
適合:
- 從一開始就知道會一直做分組(grouping)
- 經常需要
append() - 經常累加資料
例如:
from collections import defaultdict
groups = defaultdict(list)
for student in students:
groups[student.class_name].append(student)
程式通常會比 setdefault() 更簡潔。
初學者怎麼記?
可以把兩者記成:
setdefault()
「這一次,如果沒有就幫我建立。」
像:
d.setdefault(key, [])
defaultdict(list)
「以後只要沒有,都自動建立。」
像:
d = defaultdict(list)
之後便可以放心寫:
d[key].append(value)
不用再呼叫 setdefault()。
一句話總結
setdefault():需要時才建立預設值,真正行為很像set_value_default()。defaultdict(list):建立字典時就指定所有新 key 的預設值型別,之後可直接使用,不必再判斷 key 是否存在。
另外補充一個小細節:setdefault(key, default) 中的 default 每次呼叫都會先被建立(例如 [] 會先產生一個新的空 List),只是如果 key 已存在,這個新的 List 不會放進字典,而是被丟棄。因此在大量迴圈中,defaultdict(list) 通常比 setdefault(key, []) 更有效率一些。





![Python陣列介紹:List[ ], Tuple( ), Set{ }, Dictionary{ }, for迴圈 Python陣列介紹:List[ ], Tuple( ), Set{ }, Dictionary{ }, for迴圈](https://i0.wp.com/savingking.com.tw/wp-content/uploads/2022/01/1643329597-856443d20256b1a850089a56d07657bf.png?quality=90&zoom=2&ssl=1&resize=350%2C233)

![Word短篇文件編輯,TQC考題110:重點摘要與評量, \[(*)\] 萬用字元,格式>醒目提示*2次=非醒目提示 Word短篇文件編輯,TQC考題110:重點摘要與評量, \[(*)\] 萬用字元,格式>醒目提示*2次=非醒目提示](https://i1.wp.com/savingking.com.tw/wp-content/uploads/2022/03/20220322172253_75.png?quality=90&zoom=2&ssl=1&resize=350%2C233)


近期留言