dict
容器操作¶dict
是非序列式的資料結構,元素內容的儲存是成對的 key 和對應的 value。語法使用冒號組成 key 和 value 對應組 key:value
,以逗號 ,
分隔對應組元素,用大括號(curly braces){
}
成對包住所有元素。 同一個 dict
中的 value
可以存放異質類型資料。 dict
也可以是巢狀的,也就是 value
中含有另外一個 dict
類型的資料。
元素內容必須用 key
來存取,語法為 [ key ]
。
Dict 範例 | 說明 |
---|---|
{} |
空的 dict |
{'alpha': 2, 'beta': 3} |
兩個元素的 dict |
{ 'parameter': { 42: 1.5, 'angle': 30 }, 'date': ['2018-06-08'] } |
巢狀、異質的 dict |
dict([['a', 1], ['b', 2], ['c', 3]]) |
由list中建構一個新的dict物件 |
dict()
可以用來從現有物件的資料實體中生成一個新的tuple。len()
可以用來回傳容器裡key-value對的個數。dict
在建立後,元素的 value
可以就地變更(mutable),key
不可以就地變更(immutable),也不允許 mutable 的物件類型當 key
。 dict
提供的方法,請參閱官方文件 4.10 Mapping Types — dict:
clear()
清除所有容器內的內容。copy()
複製。get()
回傳某個 key 的對應 value,沒有的話就回傳預設值。pop()
回傳並移除某個 key 的對應 value,沒有的話就回傳預設值。items()
回傳可迭代的所有 (key, value) view。keys()
回傳可迭代的所有 key 的 view。values()
回傳可迭代的所有 value 的 view。dict
成員的基本操作¶extno = { 'Adam': 3030, 'Brown': 2543}
print('extno = {}'.format(extno))
extno = {'Adam': 3030, 'Brown': 2543}
# 讀取一個不存在的 key 會出現 KeyError 的錯誤
print(extno['Cathy'])
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-2-70ab3a4166b7> in <module> 1 # 讀取一個不存在的 key 會出現 KeyError 的錯誤 ----> 2 print(extno['Cathy']) KeyError: 'Cathy'
# 指定一個沒有的 key 就會新增
extno['Cathy'] = 1234
print('extno = {}, {}個成員'.format(extno, len(extno)))
extno = {'Adam': 3030, 'Brown': 2543, 'Cathy': 1234}, 3個成員
# 修改對應值
extno['Brown'] = 2567
print("Brown's extension number = {}".format(extno['Brown']))
Brown's extension number = 2567
# 刪除
del extno['Adam']
print('\nafter delete Adam, extno = {}, {}個成員'.format(extno, len(extno)))
after delete Adam, extno = {'Brown': 2567, 'Cathy': 1234}, 2個成員
# 檢查成員是否存在某個 key
print('Is Adam in the ext record? ({})'.format('Adam' in extno))
Is Adam in the ext record? (False)
# 把 Adam 加回去
extno['Adam'] = 3080
print("Add Adam back, Adam's extension number is now = {}".format(extno['Adam']))
print('extno = {}'.format(extno))
Add Adam back, Adam's extension number is now = 3080 extno = {'Brown': 2567, 'Cathy': 1234, 'Adam': 3080}
dict
成員的 Views¶# items() 的方法回傳一個 dict_items 的 view 物件,包含所有成員的成對的 key-value
print(extno.items())
# 把 view 卸載
item_list = list(extno.items())
dict_items([('Brown', 2567), ('Cathy', 1234), ('Adam', 3080)])
# keys() 的方法回傳一個 dict_keys 的 view 物件,包含所有成員的 key
print(extno.keys())
# 把 view 卸載
key_list = list(extno.keys())
dict_keys(['Brown', 'Cathy', 'Adam'])
# values() 的方法回傳一個 dict_values 的 view 物件,包含所有成員的 value
print(extno.values())
# 把 view 卸載
value_list = list(extno.values())
dict_values([2567, 1234, 3080])
dict
物件的方法¶dict()
dict.fromkeys()
dict(zip())
Python 的內建函式 zip()
可以用來將多組序列物件裡的成員,按照對應順序分拆打包在一序列的 tuple 裡。dict()
會將每個 tuple 的第一個元素當成 key。
# 可以從原本就是 key-value pair 的序列終生成
dict_from_view = dict(item_list)
print('dict from key-value sequence = {}'.format(dict_from_view))
dict from key-value sequence = {'Brown': 2567, 'Cathy': 1234, 'Adam': 3080}
# fromkeys() 可以從 list 中生成新的字典容器,value 都用預設值
dict_from_keys = dict.fromkeys(key_list, 10000)
print('dict from key list = {}'.format(dict_from_keys))
dict from key list = {'Brown': 10000, 'Cathy': 10000, 'Adam': 10000}
# zip 把兩個 list 裡的成員分拆打包成 tuple 序列
print('\ntwo lists after zipped: {}'.format(list(zip(value_list, key_list))))
two lists after zipped: [(2567, 'Brown'), (1234, 'Cathy'), (3080, 'Adam')]
# 新的 dict 用原本的 value 來當 key
dict_from_zip = dict(zip(value_list, key_list))
print('dict from zipping 2 lists = {}'.format(dict_from_zip))
dict from zipping 2 lists = {2567: 'Brown', 1234: 'Cathy', 3080: 'Adam'}
dict
物件方法¶# 成員個數
print('dict_from_view 有 {} 個成員'.format(len(dict_from_view)))
dict_from_view 有 3 個成員
# get() 的方法常見用於讀取設定檔,沒有設定的參數就回傳預設值,不會沒有這個 key 就發生錯誤
print('"Operator" 不是 dict_from_view 的成員? ({})'.format('Operator' not in dict_from_view))
print('dict_from_view["Operator"] = {}'.format(dict_from_view.get('Operator', 9999)))
"Operator" 不是 dict_from_view 的成員? (True) dict_from_view["Operator"] = 9999
# 檢查從 view 裡產生的物件
print('\ndict_from_view 的成員和 extno 都一樣嗎? ({}),\ndict_from_view 是不是跟 extno 參考同一個物件? ({})'
.format(extno == dict_from_view, extno is dict_from_view))
dict_from_view 的成員和 extno 都一樣嗎? (True), dict_from_view 是不是跟 extno 參考同一個物件? (False)
# 也可以用 copy() 複製一份新的 dict 物件
dict_from_copy = extno.copy()
print('\ndict_from_copy 的成員和 extno 都一樣嗎? ({}),\ndict_from_copy 是不是跟 extno 參考同一個物件? ({})'
.format(extno == dict_from_copy, extno is dict_from_copy))
dict_from_copy 的成員和 extno 都一樣嗎? (True), dict_from_copy 是不是跟 extno 參考同一個物件? (False)
對於可拆解出成對的 (key, value) 的序列容器或可迭代物件 S 進行操作,並生成一個新的 dict
物件。
成員的操作 | 說明 |
---|---|
{key:value for (key,value) in S} |
針對每個 S 的成員 x 做運算,運算結果生成新的 dict 物件 |
{key:value for (key,value) in S if 條件} |
針對每個*符合條件*的成員 x 做運算,運算結果生成新的 dict 物件 |
Dict comprehension 語法結構也可組成相當豐富的條件式迭代運算,但需注意dict
容器的 key 不能重複,若重複指定不同 value 給同一個 key,結果對應的 value 會是最後指定的值。
{key:value運算表示句 for x1 in S1 if 條件1
for x2 in S2 if 條件2 ...
for xN in SN if 條件N}
# 可迭代物件生成 dict 物件
print({x: str(x) for x in range(5)})
print({x: ord(x) for x in ['a', 'b', 'c']})
{0: '0', 1: '1', 2: '2', 3: '3', 4: '4'} {'a': 97, 'b': 98, 'c': 99}
# 條件式挑選部份成員作處理
print({x: x ** 2 for x in range(10) if x % 2 == 0})
{0: 0, 2: 4, 4: 16, 6: 36, 8: 64}
# 在 dict comprehension 使用巢狀迴圈,注意結果可能不如原先預期
print({k: v for k in range(1, 4) for v in range(4, 7)})
{1: 6, 2: 6, 3: 6}
# 使用 enumerate 把迭代次序當成 key
print({k: v for (k, v) in enumerate('dict comprehension')})
{0: 'd', 1: 'i', 2: 'c', 3: 't', 4: ' ', 5: 'c', 6: 'o', 7: 'm', 8: 'p', 9: 'r', 10: 'e', 11: 'h', 12: 'e', 13: 'n', 14: 's', 15: 'i', 16: 'o', 17: 'n'}
# 可以使用 zip 兩兩配對
print({k: v for (k, v) in zip(['a', 'b', 'c'], [1, 2, 3])})
{'a': 1, 'b': 2, 'c': 3}