Python 字典必學技巧:用 setdefault 優雅地處理value預設值 #若能重新命名: dict.set_value_default() 比較像實際行為; setdefault() vs defaultdict(list)

加入好友
加入社群
Python 字典必學技巧:用 setdefault 優雅地處理value預設值 #若能重新命名: dict.set_value_default() 比較像實際行為; setdefault() vs defaultdict(list) - 儲蓄保險王

在撰寫 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']}
Python 字典必學技巧:用 setdefault 優雅地處理value預設值 #若能重新命名: dict.set_value_default() 比較像實際行為; setdefault() vs defaultdict(list) - 儲蓄保險王

🔍 拆解 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 字典必學技巧:用 setdefault 優雅地處理value預設值 #若能重新命名: dict.set_value_default() 比較像實際行為; setdefault() vs defaultdict(list) - 儲蓄保險王

儲蓄保險王

儲蓄險是板主最喜愛的儲蓄工具,最喜愛的投資理財工具則是ETF,最喜愛的省錢工具則是信用卡

You may also like...

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *