iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 6
0
Software Development

從零開始學Python系列 第 6

[Day 06] 從零開始學Python - 串列(list)、Tuple(元組)、字典(dict)、集合(set):我的字典裡沒有放棄,因為我還沒有寫進去(下)

註:本文同步刊載在Medium,若習慣Medium的話亦可去那邊看呦!

接下來我們要介紹另外兩個資料型態:字典(dict)與集合(set)。
首先是字典:
字典跟串列有點類似的部分,但是它的表示方式是一個鍵(key)對一個值(value),
就好像函式一樣,一個字典裡面不會出現重覆的key,但有可能不同key對應的value剛好一樣;
這樣一來,我們就可以用key去查找其對應的value。
需要注意的是,串列是有一個固定的順序排列的,
但字典並不會有固定排序(也就是說一般我們不在意排的順序)。

key和value可以是各種不同的型態如str, int, float, bool等等,
但是key必須要是hashable的資料型態(像list就不是hashable),
value做為被對應的對象,則沒有這種限制。

字典的建立方式,可以用dict()方法,也可以用大括號{},
當中每個key和value的對應使用冒號:來分隔,
而每組key:value之間,使用逗號來分開。
同時,要取得某個key對應的value值,
就像list是用index來取得對應位置的値,字典則使用dict[key]來取得。

>>> dic0 = dict()
>>> dic0
{}
>>> dic = {'xd': 1, '放棄': False, [1,5,9]: 3}  # list是unhashable,不能作為key
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> dic = {'xd': 1, '放棄': False, 3.33: 3} # 這樣就沒問題啦!
>>> dic
{'xd': 1, '放棄': False, 3.33: 3}
>>> dic['XD'] # 在程式語言的世界裡,通常大小寫是當作不一樣的呦!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'XD'
>>> dic['xd'] # 取值
1
>>> dic['放棄']
False
>>> dic[3.33]
3

上篇提到list()可以拿來轉換,dict()也有類似的特異功能,
只要內容是剛好每一組都是兩項的就可以了!(串列/tuple/剛好兩個字元的字串...)
我們看一下範例:

>>> lol = [('易大師','我的劍,就是你的劍。'),('犽宿','死亡如風,常伴吾身。'),('阿祈爾','蘇瑞瑪!你的王已經歸來了!')]
>>> diclol = dict(lol)
>>> diclol
{'易大師': '我的劍,就是你的劍。', '犽宿': '死亡如風,常伴吾身。', '阿祈爾': '蘇瑞瑪!你的王已經歸來了!'}
>>> tul = (['a','b'],['c','d'],['e','f'],['g','h']) # 裡外兩層不管是tuple或list都沒有問題!
>>> dictul = dict(tul)
>>> dictul
{'a': 'b', 'c': 'd', 'e': 'f', 'g': 'h'}
>>> chs = ['ab','cd','13'] # 兩個字元的字串會被拆開用(但超過兩個字元就不支援了)
>>> dicchs = dict(chs)
>>> dicchs
{'a': 'b', 'c': 'd', '1': '3'}

我們可以使用類似list的方式來對字典插入或修改某個key對應的value值,
如果該key已經存在在字典,則對應的value會被覆蓋,否則就產生一個新的對應。

>>> diclol['伊澤瑞爾'] = '是時候展現真正的技術了!' # 新增
>>> diclol
{'易大師': '我的劍,就是你的劍。', '犽宿': '死亡如風,常伴吾身。', '阿祈爾': '蘇瑞瑪!你的王已經歸來了!', '伊澤瑞爾': '是時候展現真正的技術了!'}
>>> dicchs
{'a': 'b', 'c': 'd', '1': '3'}
>>> dicchs['a']='XD' # 修改
>>> dicchs
{'a': 'XD', 'c': 'd', '1': '3'}

接下來是一些常見的dict操作方法,同樣請多加練習,
讀者可能會發現很多會跟list的操作概念相同,所以可以的話,請對照著比較一下。
dict1.update(dict2) -> 將dict2的內容複製後放到dict1(key重覆時,dict2的value優先)。
del dict1['key'] -> 將dict1的**'key':'value'的對應從dict1中刪去**。
dict1.clear() -> 清空整個dict1的對應(也可以用dict1 = dict())。
'XXX' in dict1 -> 檢查dict1是否有'XXX'這個key。
dict1.keys() -> 給出整個dict1的所有key(如果需要用list的形式表達,請用list()將其框住)。
dict1.values() -> 同上,但給出的是
所有value

dict1.items() -> 給出一個一個的key:value對應(每對都以tuple形式給出)。
dict2 = dict1.copy() -> 複製一份dict1的內容,生成一個dict2的字典。
(註:如果是用dict2 = dict1,只會讓兩者共用一個字典,修改會動到同一個呦!)

我們來看一下範例:

>>> diclol['國動'] = '社 社 社社社 社社 社會搖'
>>> diclol # 前面建立的字典
{'易大師': '我的劍,就是你的劍。', '犽宿': '死亡如風,常伴吾身。', '阿祈爾': '蘇瑞瑪!你的王已經歸來了!', '伊澤瑞爾': '是時候展現真正的技術了!', '國動': '社 社 社社社 社社 社會搖'}
>>> diclol['國動'] = '社 社 社社社 社社 社會搖'
>>> diclolfame = {'國動':'還敢下來阿冰鳥!', '統神':'他的手怎麼可以穿過我的叭叭啊!'}
>>> diclol.update(diclolfame) # 合併過去,重覆的會被覆蓋
>>> diclol
{'易大師': '我的劍,就是你的劍。', '犽宿': '死亡如風,常伴吾身。', '阿祈爾': '蘇瑞瑪!你的王已經歸來了!', '伊澤瑞爾': '是時候展現真正的技術了!', '國動': '還敢下來阿冰鳥!', '統神': '他的手怎麼可以穿
過我的叭叭啊!'}
>>> del diclol['統神'] # 刪除對應的鍵值對
>>> diclol
{'易大師': '我的劍,就是你的劍。', '犽宿': '死亡如風,常伴吾身。', '阿祈爾': '蘇瑞瑪!你的王已經歸來了!', '伊澤瑞爾': '是時候展現真正的技術了!', '國動': '還敢下來阿冰鳥!'}
>>> dicchs = {'a': 123, 'c': 428, '1': '3', 'eee': 11}
>>> dicchs
{'a': 123, 'c': 428, '1': '3', 'eee': 11}
>>> dicchs.clear() # 清空字典
>>> dicchs
{}
>>>
>>> '統神' in diclolfame
True
>>> '統神' in diclol # 我們剛剛刪除了,所以'統神'不會在diclol裡
False
>>> dicn = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
>>> dicn
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
>>> dicn.keys() # 取得key
dict_keys(['a', 'b', 'c', 'd'])
>>> list(dicn.keys()) # 如果需要list型式的話就外面加一層list()
['a', 'b', 'c', 'd']
>>> dicn.values()
dict_values([1, 2, 3, 4])
>>> dicn.items()
dict_items([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
>>> dico = dicn # 直接用等號,在字典相當於貼標籤在同一個身上
>>> dico['a'] = 'XD'
>>> dico
{'a': 'XD', 'b': 2, 'c': 3, 'd': 4}
>>> dicn # 結果原先的也一起被改到了!
{'a': 'XD', 'b': 2, 'c': 3, 'd': 4}
>>> dico = dicn.copy() # 使用copy()來處理
>>> dico['a'] = 1
>>> dico
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
>>> dicn # 這樣dico和dicn就是兩個不一樣的字典囉!
{'a': 'XD', 'b': 2, 'c': 3, 'd': 4}

(註:在其他語言裡,通常把key:value對應的資料結構稱作hash或hash map)

接下來要講的是集合(set)。
集合不像字典,它的本身只有key而已,每個key都必須不重覆(就像數學學到的那樣)
要建立的方式,可以使用set(),或者使用大括號{},
當中每個key之間使用逗號連接,要增加key則使用add()。
(同樣用大括號,集合沒有value對應的部份)
集合本身也是不講求排列順序的,這點和字典一樣。

>>> st = set()
>> st # 因為空的大括號代表字典,所以要產生一個空集合只能使用set(),不能用{}
set()
>>> st.add(3)
>>> st
{3}
>>> st.add(3) # 重覆的增加相同的key不會對set造成影響
>>> st
{3}
>>> st.add('XD') # set中的key不一定要有相同的資料型態
>>> st
{'XD', 3}
>>> set('XDDDD') # 可以拿單一字串放入,會被拆開來看待(重覆的被刪去)
{'D', 'X'}
>>> set(['XDDDD','XD','XD','XDDD']) # list則會以元素為單位,此外,留意它並沒有順序。
{'XD', 'XDDDD', 'XDDD'}
>>> st1 = {'A', 'C', 'E'}
>>> st2 = {'B', 'C', 'A', 'D'}
>>> 'A' in st1 # 集合同樣也可以用in來檢查是否存在key
True
>>> 'e' in st1
False

既然是集合,可想而知就會有許多跟數學上集合對應的操作,
我們就直接來看範例:

>>> st1 & st2 # '&'(念作and, 代表'且',也就是兩者皆有才算有)和intersection都是取交集
{'C', 'A'}
>>> st1.intersection(st2)
{'C', 'A'}
>>> st1 | st2 # '|'(念作or, 代表'或',也就是兩者之一有就可以了)和union都是取聯集
{'A', 'D', 'E', 'C', 'B'}
>>> st1.union(st2)
{'A', 'D', 'E', 'C', 'B'}
>>> st1 - st2 # '-'和difference都是取差集,也就是取前者有,後者沒有
{'E'}
>>> st2 - st1
{'D', 'B'}
>>> st1.difference(st2)
{'E'}
>>> st1 ^ st2 # '^'(念作exclusive or, 代表'互斥或',也就是只能其中一個有,另一個沒有的)和symmetric_difference(太長啦!不用記XD)都是取互斥或
{'B', 'D', 'E'}
>>> st1.symmetric_difference(st2)
{'B', 'D', 'E'}
>>> st1 <= st2 # '<='和issubset代表檢查前者是否是後者的子集
False
>>> st2 <= st1
False
>>> st1.issubset(st2)
False

其他還有一些,但有需要用到時再查對應功能即可。

最後一樣來做個練習吧!

  1. 眾所周知,李嚴和劉昴星曾經比過炸龍蝦,
    請建立一個字典名為shrimp,當中
    請使用兩者的作品的名字做為key,將其做的炸蝦所使用到的材料/內容列表list做為value
    還未做完成的部分不算。請參考原本對於兩人作品的描述如下:

李嚴的作品:「我的料理是炸鳳尾蝦,就是蝦子裹碎核果去炸的,將核果搗碎後裹在蝦肉上,炸成為金黃色,不但要考慮核果跟蝦肉的比例,高低油溫的調節也需要高度的技術跟經驗的。鮮脆可口的核果外衣,經油炸之後,其香味立即倍增,堪稱人間第一美味,搭配特製醬汁來食用,味道更是妙不可言。跟醬汁巧妙的組合,這是這個炸蝦的精華所在。那個醬汁,那要先將蘋果,洋蔥等切成末之後,跟各種調味料以絕妙的比例互相調合。那個醬汁,再給我一分鐘我一定能完成的!」

劉昴星的作品:「炸的香酥的核果外衣,蝦肉(蝦子)的甘甜,與順滑可口的醬汁搭配起來,真是太棒了......我在蝦肉和外衣之間,夾了豆皮封住醬汁,如此一來,就算在油鍋裡炸,醬汁也一定不會流出來。裹著一層豆皮雲的龍蝦,名字叫做小當家特製雲龍炸蝦!」

  1. 承1,請將兩人的材料從shrimp中取出,分別放入兩個set中,並命名為'lee'跟'liu'。
    請利用set的操作,回答以下問題:
    劉昴星的作品中比李嚴的作品多用了什麼材料?
    李嚴的作品中比劉昴星的作品多用了什麼材料?
    兩人的作品都有用到什麼材料?
    假定今天李嚴能做完醬汁的話,請將新增的材料(蘋果、洋蔥)以及內容(醬汁),
    加到lee這個set中,
    接著請指出現在李嚴的作品中比劉昴星的作品多用了什麼材料?
    並請將材料和內容更新回shrimp這個字典中的對應作品。

  2. 已知有一個列表lt = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    請利用slice及其他方法來達成以下要求:
    a. 請生成一個lt1,其內容為lt的所有奇數
    b. 請生成一個lt2,其內容為lt的所有偶數
    c. 請將lt2的所有元素依序附加到lt1上
    d. 請刪除lt1當中index 7和index 1的數
    e. 請將lt1進行排序

辛苦了,這兩篇對於初學者來說應該很長,
但很基本,請多加嘗試練習,後續使用到對應用法如果還是忘記的話,
可以再回頭看著對照。
那就明天見囉!


上一篇
[Day 05] 從零開始學Python - 串列(list)、Tuple(元組)、字典(dict)、集合(set):我的字典裡沒有放棄,因為我還沒有寫進去(上)
下一篇
[Day 07] 從零開始學Python - 程式結構與流程語法:如果對手太弱太簡單,那不是很爽嗎?(上)
系列文
從零開始學Python30

尚未有邦友留言

立即登入留言