Python 字典(Dictionary)的操作運算與簡介

Sean Yeh
Python Everywhere -from Beginner to Advanced
11 min readMar 26, 2021

--

Strahov Monastery nearby, Prague, Czech Republic, photo by Sean Yeh

什麼是字典

大家應該都使用過字典吧。以查詢英文單字的經驗來說,當我們拿起一本英漢字典來查詢英文單字(例如:查詢mutable這個單字)的時候,必須先翻字典找到想查詢的mutable字的頁面。找到mutable之後,就可以閱覽對應於mutable的中文解釋。

若我們拆解前面行為,可以發現,當我們尋找mutable這單字的時候,如果字典中具備符合mutable的字(鍵)時,就可以知道對應這個英文字(鍵)的中文意思說明(值)。Python的字典就跟這個現實世界的概念很想。

在Python中,字典(Dictionary)這種資料型態即以「鍵」、「值」成對的方式(key-value pair)儲存。我們可以透過鍵來查詢對應的值。其中「鍵」必須是獨一無二,但不同的鍵可對應到一樣的值。字典的標示方式是以大括號( { } )來標示。下面是字典的語法:

{key1:value1, key2:value2, ... keyN:valueN}

建立字典後,我們就可以透過「鍵」來取「值」,也可以透過新增鍵來添加新的紀錄到字典中。

與串列(list)比較

字典與串列(list)、元組(tuple)和集合(set)等,都是Python中的主要資料結構。其中串列與字典這兩種資料結構,在我們使用Python撰寫程式時,也是兩個最常使用的資料型態。因此,我們可以透過比較,來理解這兩種結構的異同。

# 儲存的類型

從兩者儲存的類型來看,字典和串列都可以儲存任何類型的物件。

# 索引方式

在存取資料時,需要索引方式。就串列來說,其索引的方式是依靠連續的整數作為索引的足標,因為串列的值會依照事先排好的順序擺放在串列中,索引值必須是整數;

而字典則透過鍵(key)作為存取資料的索引,利用「鍵」與「值」關聯在一起。而字典的索引值(也就是「鍵」)可以是數字、字串、或其他不可變且可以雜湊(可以透過__hash__算出雜湊值)的Python物件。

# 序列方式

前面提過,串列是有序的資料,順序對於串列來說非常的重要。舉例來說,就算是兩個串列中的內容一樣,僅只是存放的「順序」不同,這兩個串列還是會被判斷為不同;而字典基本上是無序的資料,在字典中沒有所謂的「第一個項目」,除非經過特別處理,裡面的資料是不會依照順序排列。

雖然在Python3.7以上的字典中,字典可以記住鍵值的插入順序,但是我們仍然無法透過 dic[0]、dic[1]的方式來提取資料。

# 可否切片

串列可以透過slice切片;字典沒有順序性,因此不可以切片。

字典的操作

建立字典

建立一個空白字典的方式很簡單,只要將變數指定為大括號 {} 就可以了。

a_dic = {}

為字典增加鍵值

針對前面的空字典a_dic我們可以替它加入新的值。例如,我們可以替這個字典加入CSS色碼對應,例如黑色的色碼為「# 000000」,白色的色碼為「# FFFFFF」

a_dic['black'] = '#000000'a_dic['white'] = '#FFFFFF'

依鍵取值

增加資料後,我們可以透過「鍵」取出對應的值。例如我們可以透過下面方式取得黑色的色碼:

balck = a_dic['black']print(black)

執行結果如下:

也可以查看字典的內容:

print(a_dic)

執行結果如下:

len()

與list一樣,對字典使用len方法也可以傳回字典內容的個數。

len(a_dic)

執行結果如下:

keys()

使用keys方法,可以傳回字典中所有的鍵。例如:

a_dic.keys()

執行結果如下:

values()

另外,我們可以透過values方法傳回字典中所有的值。例如:

a_dic.values()

執行結果如下:

items()

傳回字典中所有的鍵與值,每一組鍵與值會放在一組tupple裡面。例如:

a_dic.items()

執行結果如下:

for迴圈

在使用上面keys、values、items三種方法時,for迴圈可以分別的迭代出字典中的鍵、值和鍵值對。如果要透過上述方式取得串列的值,就必須把這些返回值再次傳入串列list函式來進行轉換。

in和not in

我們可以透過in和not in檢查某個鍵或值是否在字典中。

get()

當鍵存在字典的時候,使用get方法可以傳回對應鍵的值,反之若不存在鍵的時候,則傳回None。透過這個方式可以簡化前面使用in與not in的檢查步驟。

a_dic.get('name')

setdefault()

當鍵存在字典的時候,使用get方法可以傳回對應鍵的值,反之若不存在鍵的時候,則傳回第二個參數的值,並以傳入的參數來新增該鍵的值。

a_dic.setdefault('name',None)

以上面程式碼為例,如果找不到name時,會新增一個name的鍵,並且提供None作為該鍵的值。

copy()

製作一個淺層複製。也就是說copy會製造出一個字典副本。

a_dic.copy()

update()

update可以合併兩個字典。它會用其他字典的內容(b_dic)來更新(a_dic)字典內容。假如合併的是原本字典(a_dic)中所不存在的鍵值,則合併後會直接新增該鍵值;然而若兩個字典中有共通的鍵,(a_dic)字典中的值將會被覆蓋。

a_dic.update(b_dic)

字典的應用

雖然字典沒有順序,但是我們可以使用幾乎任意的值當作『鍵』,這能讓我們在整理資料獲得強大的力量。例如,我們可以透過字典紀錄朋友的生日(key為名稱,value為出生年月日)。

A. 井字遊戲

井字遊戲是我們小時候常常玩的OX遊戲,在外國的程式教學上面常常會提到這個範例,如果你看到Tic Tac Toe 就是指這種遊戲。

這個遊戲很簡單,就是在紙上畫出有像井字一般的九個格子(九宮格),由遊戲的玩家雙方依序填入O或者是X,當某一方率先連成一條線的時候,該玩家就是勝利者。

Tic Tac Toe

我們在此關心的是Python字典要在這個遊戲裡面扮演什麼角色?其實,我們可以把遊戲的每一局設想為一個具有九個鍵值的字典。其中座標為鍵、玩家輸入的O或X為值。

下面是我們將一個九宮格的棋局標上座標,就橫向來看,第一排稱為 Head中間為Body最下面為Foot(這命名方式參考HTML的table);就縱向來看第一欄為Left(左)、第二欄為Center(中)、第三欄為Right(右)(這命名方式參考CSS的Box Model)。

我們把上面的規劃用程式碼表現,結果如下:

gameBoard = {'hl':' ', 'hc':' ', 'hr':' ','bl':' ', 'bc':' ', 'br':' ','fl':' ', 'fc':' ', 'fr':' '}

如果要在特定位置輸入OX,我們可以使用字典的dic[key]為字典增加鍵值。例如在中間欄位填入O的話,可以採用下面方式:

gameBoard['bc'] = 'O'

又如,要在左下角填入X的話,可以採用下面方式:

gameBoard['fl'] = 'X'

我們在此只說明字典的應用,不會完成整個遊戲,大家有興趣的話可以上網查詢這個遊戲的製作方式,或者您也可以自行動手寫看看。

B.對應關係轉換

假設你有一個需要把A值,對應到B值的需要。這是後,選擇使用字典是一個不錯的方式。當我們在製作一組資料集合時(譬如說一個兩欄標題並且有數列資料的excel表格),透過字典的格式,並且輔以map來作轉換,是一個很方便的方法。

下面我們假設有一個DataFrame,裡面有產品與數量兩個欄位。

mydata = pd.DataFrame({'product':['iphone12','MacBookAir','MacBookPro','AppleTV','AirPod'],'item'[4,3,12,6,7]})

實際上,產品與數量的欄位組合也是一個字典,product與item為鍵,其他部分為值。DataFrame表格如下所顯示:

現在,我們需要多一個欄位,這個欄位需要逐一的說明每個產品的類別(category)。在這個狀況下,我們可以使用一個鍵與值對應的字典來處理這個對照的問題。雖然在目前的案例下,您可能會覺得資料才五筆,透過手工輸入就好,何需另外寫一個程式?然而,若情況變成需處理的資料不僅是五筆,而是五百筆、五千筆甚至於是五萬筆的話,您是否會改變先前的想法?

在這樣子的情況下,我們有一個product_to_category的字典,將每個產品分別定義它的類型:

product_to_category = {'iphone12':'mobile','MacBookAir':'laptop','MacBookPro':'laptop','AppleTV':'home kids','AirPod':'accessory'}

然後再使用map將對應的結果一口氣填入category欄位中:

mydata['category'] = mydata['product'].map(product_to_category)

這樣子我們就得到三個欄位的表格:

C. Flask Session的使用

當我們的網站有時需要將使用者的資料存在session中,供後續使用。這個session實際上是以字典形式來表現。例如我們想在session存入一個start值,可以使用session[‘start’]=值的方式來處理。

由於在使用字典的時候,若需要的鍵不存在的話,會發生KeyError錯誤。為了避免這種錯誤的發生,可以使用get取回session資訊,避免出現錯誤。

start = session.get('start')

假使您不需要將表單輸入的內容存入可以維持時間更久的資料庫中的話,可以使用下面方式來處理:下面是我們在Flask Web中使用session來儲存表單資料的方式,我們把session寫入一個home view裡面。

@core.route('/',methods=['GET','POST'])def home():
form = Form()
if form.validate_on_submit():
session['start'] = form.start.data
session['end'] = form.end.data
session['dir'] = form.dir.data
start = session.get('start')
end = session.get('end')
dir = session.get('dir')
return render_template('home.html',form=form, start=start, end=end, curr=dir)

總結

在這篇裡面,已經說明了大部分與Python字典有關的知識。字典與串列都是很有用的兩個資料方式,都可以存放多重的值。字典不僅可以用整數當作鍵,也可以使用字串或元組、或其他不可變且可以雜湊的Python物件當作鍵。另外,Python字典執行起來速度非常之快速、效率非常的高。大家在撰寫自己專案時可以思考看看該如何使用。

--

--

Sean Yeh
Python Everywhere -from Beginner to Advanced

# Taipei, Internet Digital Advertising,透過寫作讓我們回想過去、理解現在並思考未來。並樂於分享,這才是最大贏家。