Python 字典推導式詳解:新手指南
更新日期: 2024 年 10 月 3 日
在 Python 編程中,字典(Dictionary) 是一種非常重要的數據結構,用於存儲 鍵-值對(key-value pair)。
為了高效地創建和操作字典,Python 提供了 字典推導式(Dictionary Comprehension),這是一種簡潔而強大的語法,允許我們以單行代碼創建字典。
對於剛開始學習 Python 的新手來說,理解並掌握字典推導式將大大提升您的編程效率和代碼可讀性。
本文將詳細介紹 Python 中的字典推導式,包括其基本概念、語法、使用方法、實際應用和注意事項,幫助您在實際開發中靈活運用。
什麼是字典推導式?
定義
字典推導式 是一種基於已有的可迭代物件(如串列、元組、字典等),按照一定的表達式和條件,快速生成新字典的方式。
它類似於串列推導式,但生成的是字典。
特點
- 簡潔明了:以單行代碼創建字典,代碼更簡潔。
- 高效:比使用傳統的迴圈創建字典更高效。
- 可讀性強:清晰地表達字典的構建方式,易於理解。
字典推導式的基本語法
語法格式
{key_expression: value_expression for item in iterable if condition}
key_expression
:鍵的表達式,定義字典中鍵的計算方式。value_expression
:值的表達式,定義字典中值的計算方式。iterable
:可迭代物件,如串列、元組、字典等。condition
(可選):過濾條件,只有滿足條件的項才會被包含在字典中。
示例
基本示例:
squares = {x: x**2 for x in range(1, 6)}
print(squares)
輸出:
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
解釋:
x
:迭代變量,取值為 1 到 5。x: x**2
:鍵為x
,值為x
的平方。
字典推導式的使用方法
從串列創建字典
示例:
names = ['Alice', 'Bob', 'Charlie']
name_lengths = {name: len(name) for name in names}
print(name_lengths)
輸出:
{'Alice': 5, 'Bob': 3, 'Charlie': 7}
解釋:
- 鍵:名字
name
。 - 值:名字的長度
len(name)
。
從字典創建新的字典
示例:
original_dict = {'a': 1, 'b': 2, 'c': 3}
doubled_values = {key: value * 2 for key, value in original_dict.items()}
print(doubled_values)
輸出:
{'a': 2, 'b': 4, 'c': 6}
解釋:
original_dict.items()
:返回鍵值對的元組串列。- 鍵:保持不變
key
。 - 值:原值乘以 2。
添加條件過濾
示例:
numbers = range(10)
even_squares = {x: x**2 for x in numbers if x % 2 == 0}
print(even_squares)
輸出:
{0: 0, 2: 4, 4: 16, 6: 36, 8: 64}
解釋:
- 條件:
if x % 2 == 0
,只保留偶數。 - 鍵:偶數
x
。 - 值:偶數的平方
x**2
。
實際應用示例
交換字典的鍵和值
示例:
original_dict = {'a': 1, 'b': 2, 'c': 3}
reversed_dict = {value: key for key, value in original_dict.items()}
print(reversed_dict)
輸出:
{1: 'a', 2: 'b', 3: 'c'}
解釋:
- 鍵:原字典的值
value
。 - 值:原字典的鍵
key
。
將兩個串列合併成字典
示例:
keys = ['name', 'age', 'city']
values = ['Alice', 25, 'Taipei']
combined_dict = {k: v for k, v in zip(keys, values)}
print(combined_dict)
輸出:
{'name': 'Alice', 'age': 25, 'city': 'Taipei'}
解釋:
zip(keys, values)
:將兩個串列組合成元組對。- 鍵:
k
,即keys
中的元素。 - 值:
v
,即values
中的元素。
過濾字典中的項
示例:
scores = {'Alice': 85, 'Bob': 92, 'Charlie': 78}
passed = {name: score for name, score in scores.items() if score >= 80}
print(passed)
輸出:
{'Alice': 85, 'Bob': 92}
解釋:
- 條件:
if score >= 80
,只保留分數大於等於 80 的學生。 - 鍵:學生姓名
name
。 - 值:學生分數
score
。
字典推導式的進階用法
嵌套字典推導式
示例:
nested_dict = {i: {j: i * j for j in range(1, 4)} for i in range(1, 4)}
print(nested_dict)
輸出:
{
1: {1: 1, 2: 2, 3: 3},
2: {1: 2, 2: 4, 3: 6},
3: {1: 3, 2: 6, 3: 9}
}
解釋:
- 外層鍵:
i
,取值為 1 到 3。 - 內層字典:
{j: i * j}
,j
取值為 1 到 3。
結合串列推導式
示例:
words = ['apple', 'banana', 'cherry']
word_lengths = {word: [word(char) for char in word] for word in words}
print(word_lengths)
輸出:
{
'apple': [97, 112, 112, 108, 101],
'banana': [98, 97, 110, 97, 110, 97],
'cherry': [99, 104, 101, 114, 114, 121]
}
解釋:
- 鍵:單詞
word
。 - 值:單詞中每個字符的 ASCII 編碼串列。
使用注意事項
鍵的唯一性
- 注意:字典中的鍵必須是唯一的,如果在推導過程中產生了相同的鍵,後面的值會覆蓋前面的值。
示例:
numbers = [1, 2, 2, 3]
square_dict = {x: x**2 for x in numbers}
print(square_dict)
輸出:
{1: 1, 2: 4, 3: 9}
解釋:
- 數字
2
出現兩次,但字典中鍵2
只能有一個,故只保留最後一次的值。
可讀性
- 建議:在使用複雜的推導式時,應注意代碼的可讀性,必要時可以拆分成多行或使用傳統迴圈。
示例:
# 複雜的推導式,可能降低可讀性
complex_dict = {k: v for k in keys if condition for v in values if other_condition}
建議:簡化推導式,或使用多行代碼實現。
運算效率
- 性能:字典推導式通常比傳統迴圈更高效,但在處理大量數據時,仍需注意性能問題。
常見錯誤與調試
SyntaxError
- 原因:語法錯誤,可能是漏寫了冒號、括號等。
示例:
# 缺少冒號
squares = {x x**2 for x in range(5)}
# SyntaxError: invalid syntax
解決方案:檢查語法,確保正確使用冒號和括號。
KeyError
- 原因:在推導式中訪問了不存在的鍵。
示例:
dict1 = {'a': 1, 'b': 2}
dict2 = {dict1[key]: key for key in ['a', 'c']}
# KeyError: 'c'
解決方案:在迭代前確認鍵是否存在,或使用 dict1.get(key)
方法。
ValueError
- 原因:在推導式的條件中出現錯誤。
示例:
numbers = [1, 2, 3]
square_dict = {x: x**2 for x in numbers if x > 0 else 'negative'}
# SyntaxError: invalid syntax
解決方案:推導式中的條件部分不能使用 if-else
,需要將 if-else
表達式放在前面。
正確示例:
square_dict = {x: x**2 if x > 0 else 'negative' for x in numbers}
總結
- 字典推導式 是創建字典的簡潔方式,語法類似於串列推導式。
- 基本語法:
{key_expression: value_expression for item in iterable if condition}
。 - 優勢:
- 簡潔明了,提高代碼可讀性。
- 高效創建字典,性能優於傳統迴圈。
- 注意事項:
- 鍵必須唯一,否則後面的值會覆蓋前面的值。
- 避免過於複雜的推導式,保持代碼可讀性。
- 注意語法細節,防止常見錯誤。