字典
簡介
上個章節介紹了串列,接下來這個章節我們看看在 Python 中使用率也很高的資料類型:字典(Dictionary)。
在開始介紹字典之前,先想一下,如果是要用來裝資料的「容器」,像藥盒子一樣的串列不夠用嗎?為什麼需要其他的資料結構?舉個例子:
data = ["弗利沙", [10, 20], (1, 23, 530000)]
你光看這些資訊,有辦法一眼就看出來 [10, 20]
或是第三個元素裡的 23
分別代表什麼意思嗎?也許這是你設計的所以你現在看的懂,但對其他人或是幾個月之後的自己,可能就不是這麼一回事了。如果能幫這些資料加上「標籤」,識別度會更好一些,這時候字典就能派上用場了。
創建字典
Python 的字典可以幫資料加上更多說明,讓資料的意義更明確。字典的最外層使用大括號 { }
包起來,裡面則是由「鍵(Key)」以及「值(Value)」所組成。建立字典不需要使用任何函數,直接用大括號就可以開始寫,像這樣:
data = {"name": "弗利沙", "level": [10, 20], "power": (1, 23, 530000)}
這裡的 "name"
、"level"
以及 "power"
就是 Key,後面對應的就是 Value。Key 等於是在幫 Value 加上標籤,這樣可以更清楚的知道每個值所代表的意義,這也是它被稱為「字典」的原因。不使用大括號的話,也可以使用 dict()
來建立字典:
data = dict(name="弗利沙", level=[10, 20], power=(1, 23, 530000))
這樣也能建立字典。
dict()
還能使用其他像是串列 或 Tuple 等巢狀資料結構來建立字典:
>>> user1 = [["name", "悟空"], ["hp", 80], ["power", 100]]
>>> user2 = (("username", "魯夫"), ("hp", 100), ("mp", 70))
# 把巢狀陣列轉換成字典
>>> hero1 = dict(user1)
>>> hero1
{'name': '悟空', 'hp': 80, 'power': 100}
# 把巢狀 Tuple 轉換成字典
>>> hero2 = dict(user2)
>>> hero2
{'username': '魯夫', 'hp': 100, 'mp': 70}
只要給它成對的資料,不管是串列或是 Tuple,或甚至混著用也沒關係,dict()
都能把它們轉換成字典。
不過,如果沒特別需求的話,我自己比較喜歡直接用字面值(Literal),也就是大括號 { }
來建立字典,程式碼看起來比較清楚。事實上,使用 dict()
建立字典物件的過程中會經歷的步驟比用字面值 { }
多了一點點,因此使用 dict()
的執行速度也會比 { }
慢一點點。
是說,dict
的發音,最後一個 t
的發音要唸清楚,不然聽起來就會像「dick」,這個字在英文...嗯,有別的意思,如果怕唸錯的話可以唸做 Dictionary
,或是直接叫它「字典」就好。
雖然之前有稍微提過但我猜大家可能沒放心上,就是 str()
、int()
、float()
、bool()
、list()
這些看起來像函數的東西,為了簡化或是避免造成學習上的困惑,在這本書裡我大部份時候都會稱它們為「函數」,但實際上在 Python 裡它們都是「類別(Class)」,dict()
也是。關於類別的詳細內容會在物件導向章節介紹,
在 dict
類別身上 有一個 .fromkeys()
方法,也可以用來建立字典:
>>> hero = dict.fromkeys(["name", "age", "power"])
>>> hero
{'name': None, 'age': None, 'power': None}
.fromkeys()
方法的第一個參數是可迭代物件,所以要用字串、串列或 Tuple 都可以,我就先給它一個串列。串列裡的每個元素會被當作 Key 並且建立一個全新的字典,然後所有的 Value 預設都會被設定成 None
。如果想要改變預設值,可以多加一個參數:
>>> hero = dict.fromkeys(["name", "age", "power"], 0)
>>> hero
{'name': 0, 'age': 0, 'power': 0}
這樣就會建立一個所有值都是 0
的新字典。要注意的是,因為字串也是可迭代物件,所以如果這裡把一個字串放進第一個參數:
>>> user = dict.fromkeys("hello", "kitty")
>>> user
{'h': 'kitty', 'e': 'kitty', 'l': 'kitty', 'o': 'kitty'}
"hello"
字串的每個字元會被當作 Key,Value 會被設定成 kitty
,又因為剛好 hello
裡面有一個重複的 l
,所以有一組就被蓋掉了。我不確定這是不是你預期的結果,使用的時候需要稍微留意一下。
取用字典
存取字典的方式跟串列有點類似,串列是連續的記憶體空間,所以是使用索引值來存取裡面的元素,但字典本身並沒有順序,所以不是使用索引值來存取資料,取而代之的是使用 Key 來存取資料:
>>> user = {"name": "地球人", "age": 20, "power": 5}
# 使用 Key 來存取
>>> user['name']
'地球人'
>>> user['age']
20
>>> user['power']
5
字典裡查的到的 Key 都很正常,但如果用一個不存在的 Key 來查資料,有些程式語言只是安靜的給你一個 undefined
或 nil
然後裝做什麼事都沒發生,但 Python 又會再次給你很明確的錯誤訊息:
>>> user['hello']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'hello'
恭喜你得到了一個 KeyError
的錯誤訊息。雖然萬一跳出這個錯誤訊息也是可以用 try...except...
救回來,但如果每次要查個 Value 就要做錯誤處理也未免有點太辛苦了,錯誤處理相關的介紹會在後面的章節再詳述。要是擔心會遇到不存在的 Key 的情況,可以用 in
關鍵字判斷一下:
user = {"name": "地球人", "age": 20, "power": 5}
if "hello" in user:
print(user["hello"])
else:
print("是在哈囉?")
這樣就能避免找不到 Key 的情況。不過 Python 的字典物件本身就有提供一些方法,可以在查詢的時候遇到沒有 Key 的情況也不會出錯,還可以給個預設值:
>>> user = {"name": "