字典

April 11, 2022

字典(dict)物件是儲存鍵(key)/值(value)對應的物件,為 dict 的實例。

dict 操作

直接示範如何以實字建立 dict 物件:

>>> passwords = {'Justin' : 123456, 'caterpillar' : 933933}
>>> passwords['Justin']
123456
>>> passwords['caterpillar']
933933
>>> passwords['Hamimi'] = 970221
>>> passwords
{'caterpillar': 933933, 'Hamimi': 970221, 'Justin': 123456}
>>> passwords['Hamimi']
970221
>>> del passwords['caterpillar']
>>> passwords
{'Hamimi': 970221, 'Justin': 123456}
>>>

建立 dict 時,作為鍵的元素必須是 hashable,也就是實作了 __hash____eq__ 方法,鍵是用來與值物件對應,指定鍵物件取得值物件時是使用 [] 運算子,如果要刪除某個鍵/值,則可以使用 del

直接使用 [] 指定鍵要取得值時,若 dict 沒有該鍵的存在,會丟出 KeyError。可以使用 in 來測試鍵是否存在於 dict 中。例如:

>>> passwords['caterpillar']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'caterpillar'
>>> if 'caterpillar' in passwords:
...     print(passwords['Justin'])
... else:
...     print(None)
...
None
>>> print(passwords.get('caterpillar'))
None
>>> print(passwords.get('caterpillar', 'NO_PASSWORD'))
NO_PASSWORD
>>>

上例中,get 方法指定的鍵若不存在,預設會傳回 None 而不是丟出錯誤,get 可以指定預設值,在指定的鍵不存在時就傳回預設值。

可以使用 update 合併 dict,使用 pop 方法將對應的鍵/值取出並從 dict 移除。例如:

>>> passwords
{'Hamimi': 970221, 'Justin': 123456}
>>> passwords.update({'Momor' : 670723})
>>> passwords
{'Hamimi': 970221, 'Justin': 123456, 'Momor': 670723}
>>> passwords.pop('Justin')
123456
>>> passwords
{'Hamimi': 970221, 'Momor': 670723}

Python 3.9 以後,可以透過 | 來更簡單地合併 dict,若作為運算元的 dict 有重複鍵值,傳回的 dict 會使用 | 右運算元的鍵值,例如:

>>> passwords = {'Hamimi': 970221, 'Justin': 123456}
>>> passwords | {'Momor' : 670723}
{'Hamimi': 970221, 'Justin': 123456, 'Momor': 670723}
>>> d1 = {'a': 10, 'b': 20}
>>> d2 = {'b': 30, 'c': 40}
>>> r = d1 | d2
>>> r
{'a': 10, 'b': 30, 'c': 40}
>>>

鍵/值

如果要取得 dict 中全部的鍵/值,則可以使用 items 方法,這會傳回 dict_items 物件,當中是以 tuple 儲存每組鍵/值。

如果只是要取得全部的鍵,可以使用 keys 方法,這會傳回 dict_keys 物件;如果只是要取得全部的值,可以使用 values 方法,這會傳回 dict_values 物件。例如:

>>> for person in passwords:
...     print(passwords[person])
...
970221
670723
>>> passwords.items()
dict_items([('Hamimi', 970221), ('Momor', 670723)])
>>> for item in passwords.items():
...     print(item)
...
('Hamimi', 970221)
('Momor', 670723)
>>> passwords.keys()
dict_keys(['Hamimi', 'Momor'])
>>> for key in passwords.keys():
...     print(key)
...
Hamimi
Momor
>>> list(passwords.keys())
['Hamimi', 'Momor']
>>> passwords.values()
dict_values([970221, 670723])
>>> for value in passwords.values():
...     print(value)
...
970221
670723
>>> list(passwords.values())
[970221, 670723]
>>>

在 Python 3.5 以前,不保證鍵的順序,Python 3.6 開始,會以字面值時每對鍵值的撰寫順序,或者 dict 的安插順序來作為 itemskeysvalues 的迭代順序,並且這在 Python 3.7 成為正式特性。

在 Python 3.7 以後,要小心使用這個特性,務必確認你操作的是 dict 實例,而不是長得像 dict 的實例;在 Python 3.7 之前,若要保證順序,可以使用 collections.OrderedDict

itemskeysvalues 為什麼不直接傳回 list 呢?若 dict 中有許多鍵值,相較於建立一個夠長的 list 來儲存這些元素,itemskeysvalues 的作法比較經濟,因為 dict_itemsdict_keysdict_values 傳回後,尚未實際取得 dict 的對應鍵值,只有在真正需要下個元素時,才會進行相關運算,這樣的特性稱為惰性求值(Lazy evaluation)。

itemskeys 傳回的物件具有集合的行為,可以與集合物件進行運算,values 則否,因為值不一定是唯一(不同的鍵可能有相同的值)。例如:

>>> passwords.items() | {'x', 'y'}
{'y', ('Momor', 670723), 'x', ('Hamimi', 970221)}
>>> passwords.keys() | {'x', 'y'}
{'y', 'x', 'Hamimi', 'Momor'}
>>> passwords.values() | {'x', 'y'}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'dict_values' and 'set'
>>>

除了實字表示方式之外,也可以使用 dict 建立實例。例如:

>>> passwords = dict(justin = 123456, momor = 670723, hamimi = 970221)
>>> passwords
{'hamimi': 970221, 'justin': 123456, 'momor': 670723}
>>> passwords = dict([('justin', 123456), ('momor', 670723), ('hamimi', 970221)])
>>> passwords
{'hamimi': 970221, 'justin': 123456, 'momor': 670723}
>>> dict.fromkeys(['Justin', 'momor'], 'NEED_TO_CHANGE')
{'Justin': 'NEED_TO_CHANGE', 'momor': 'NEED_TO_CHANGE'}
>>>

分享到 LinkedIn 分享到 Facebook 分享到 Twitter