【Python基礎教學】match…case&函數&字典【part-6】

哈囉大家好,很感謝你點進本文章,我是一名高中生,是電腦社社團的社長,由於我並不是 Python 這方面非常精通的專家,所以若文章有些錯誤請見諒,也可向我指正錯誤。另外本文章的用意是作為電腦社社團的教材使用而編寫的。

接下來,讓我們進入正題。

在上次我們談完了條件控制及運算子後,我們繼續前進,來到函數及迴圈的世界。

函數的概念我們在 Part 2 的部分已經有談到小部分,print() 是一個函數,不過這種格式的函數只能用來呼叫(call)它,不能夠定義且宣告它。

不過本次教學就要來教各位如何在 Python 中,宣告且定義它。在此之前,我們先來說說上次未說完的條件控制:

match…case

※註:match…case 這個功能只有在 Python 3.10 以上版本才有。

match…case 是 python 版的 switch…case,在其他程式語言如:C 語言使用的語法就是 switch…case。

那麼要 match…case 做什麼用呢?主要是用於簡化 if… else 的判斷,能夠使程式碼變得更加簡明扼要。

match 後的物件會依序與 case 後的內容進行匹配,如果匹配成功,則執行匹配到的表達式,否則直接跳過,_可以匹配一切。

而 case : 類似於 C 語言、Java 裡面的 default:,意思就是當 case : 上面所有條件都不吻合時,那麼 case _: 就必定會成功匹配,執行它裡面的內容。

語法格式如下:

1
2
3
4
5
6
7
match expression:
case pattern1:
# 處理 pattern1 的邏輯
case pattern2 if condition:
# 處理 pattern2 並且滿足 condition 的邏輯
case _:
# 處理其他情況的邏輯

參數說明:

  • match 語句後方接一個運算式,然後使用 case 語句來定義不同的模式。
  • case 後面接著一個模式,可以是具體值、變數、萬用字元(wildcard character、大陸翻譯為通配符)等。
  • 可以使用 if 關鍵字在 case 中添加條件。
  • _ 通常用於萬用字元,匹配任何值。

image

圖源:Python match…case Statement (With Examples)

為了讓大家對於 match…case 的語法更加清晰,所以我們來做以下範例:

1
2
3
4
5
6
7
8
9
10
11
mystatus = 404

match mystatus:
case 400:
print("Bad request")
case 404:
print("Not Found")
case 418:
print("I'm a teapot")
case _:
print("Something's wrong with the internet")

註:改自菜鳥教程之範例。

一個 case 也可以設定多個條件,使用|隔開,例如:

1
2
3
...
case 401|403|404:
return "Not allowed"

進階用法


(2024/08/03補)

  1. 字典匹配:
1
2
3
4
5
6
7
8
item = {"type" : "fruit", "name" : "apple"}
match item:
case {"type": "fruit", "name": "apple"}:
print("This is an apple.")
case {"type": "fruit", "name": "orange"}:
print("This is an orange.")
case _:
print("Unknown item.")

輸出:

1
This is an apple.
  1. 元組匹配
1
2
3
4
5
6
7
8
point = (1, 1)
match point:
case (0, 0):
print("Origin")
case (x, y) if x == y:
print(f"Diagonal at {x}, {y}")
case (x, y):
print(f"Point at {x}, {y}")

輸出:

1
Diagonal at 1, 1

函數(Function)

函數,我們可以把它想成是自動販賣機,就如我在 Part 2 時所說的一樣,如有疑慮請至:【Python基礎教學】開發環境介紹&基礎程式設計【part-2】

(2024/08/03改)在程式設計中,函式(Function)是一個封裝好的代碼塊,具有以下幾個性質:

  • 可重用性(Reusability):函式是一段可以多次重複使用的程式碼。定義一次後,可以在程式中的不同地方呼叫,不必再寫一次一樣的代碼,這也是為什麼我們需要學習函數的原因。
  • 模組化(Modularity):函式能將程式分解成較小的一塊模組,每個模組(即函式)負責完成特定的任務。這樣的結構會使程式更容易理解和維護。比如說:有負責處理主程式碼的中心函數,由他分別呼叫個別的函數,這樣能達成模組化的目的。
  • 封裝性(Encapsulation):函式內部所定義的程式碼和變數通常是被封裝的(局域變數),不會直接影響或被程式其他部分影響。這樣可以降低不同代碼段之間的耦合度。簡單講就是在函數中的程式碼不會被輕易修改。
  • 輸入和輸出(I/O:Input and Output):函式通常接受輸入參數(Arguments),進行處理後,回傳一個結果。輸入參數和回傳值的存在使得函式可以更加靈活地處理不同的資料。
  • 抽象化(Abstraction):可透過函式減少重複代碼,使程式碼更具可讀性和邏輯性。例如,數學函式可以代表數學公式,處理資料的函式可以表示特定的資料處理邏輯。簡單說就是使用者在使用時能夠更加方便,不會太過於複雜。(如果你是使用者,看到這麼多程式碼抑或是介面那麼複雜的話,你會想用這軟體嗎?)
  • 作用域(Scope):函式內部定義的變數通常只在函式內部才能被修改,這些變數有自己的作用域,不會影響到外部的變數。
  • 遞迴(Recursion):函式自己呼叫自己,稱為遞迴。這在需要處理巢狀結構(例如我們常見的資料夾開開關關就是一種巢狀的結構)或重複性任務時非常有用。-> 這非常非常重要!

接下來,我們來學習如何定義一個函數:

image

圖源:Python Function | Board Infinity

首先,我們得知道在 Python 中,定義函數的關鍵字為「def」,而它放在函數名稱的開頭。

接下來,我們輸入函數名稱,加上左右括號,如:「def myfunction()」

在這括號裡面呢,我們可以填入一些變數,作為函數的參數(parameter)。而參數與引數(argument)不同的是:

參數是在建立函數時,預設定義宣告的變數。

引數是在呼叫函數時,指定變數(引入數值)數值。

然後不要忘記,重要的地方來了:我們要在我們建立的函數最後,加上一個冒號(半形)「:」。

最後我們建立函數的格式就變成這樣:「def function():」

另外,再教給各位在函數的觀念中,非常重要的概念:return [expression]。return,又稱為迴轉、回傳、傳回、返回等都是它的中文意思,將它放在函數裡面,代表立馬結束函數,return 下方的程式碼將不會執行,直接回傳數值給呼叫方的函數。

若 return 後面沒東西的話,則回傳 None,也就是無的意思。

以下是一個函數的範例:

1
2
3
4
5
def fun():
if a > b:
return a
else:
return b

這函數表示若 a > b,那麼就回傳 a 數值,否則(else)回傳 b 數值。

接下來我們透過一個簡單的範例來練習如何定義一個函數:

1
2
3
4
def hello() :
print("Hello World!")

hello()

可以看到我們定義一個函數名稱為 hello(),然後要注意的是最後面一定要加上冒號,裡面內容則是又放入了一個函數 print(“Hello World!”),而我們看到最後一行,我們對這個函數進行了呼叫,於是這個函數就會執行裡面的 print(“Hello World!”)。

不過我們還可以運用前面所學到的參數,來將 Hello World 替換掉,如下方所示:

1
2
3
4
def text(text):
print(text)

text("Hello")

前面就有說到,函數主要拿來處理一些重複性的問題,所以這種只有一行的程式碼就不需要直接寫入函數內,目前只是為了教學方便而使用此範例。

接下來,讓我們來做更多例子,來加深我們對於函數的記憶:

以下是一個計算平面中矩形的面積函數程式:

1
2
3
4
def area(width, height):
return width * height

print("width = 10, height = 10, area = ", area(10,10))

然後是計算質因數的程式:

1
2
3
4
5
6
7
8
9
10
11
def calculate_the_factor(num):
if num % 2 == 0:
print(num, " 有 2 的因數")
if num % 3 == 0:
print(num, "有 3 的因數")
if num % 5 == 0:
print(num, "有 5 的因數")
if num % 7 == 0:
print(num, "有 7 的因數")

calculate_the_factor(72)

在這個程式你可以發現,一個一個寫判斷式很麻煩,所以在下一章介紹迴圈時,同時也會教各位如何用比較簡潔的方式來撰寫這支程式。

參數(parameter)

參數在函數中被視為非常重要的一部分,而以下是呼叫函數時可用的正式參數類型:

  • 位置參數(Positional Arguments)
  • 關鍵字參數(Keyword Arguments)
  • 默認參數(Default Arguments)
  • 可變位置參數(*args):允許函式接收任意數量的位置參數。
  • 可變關鍵字參數(**kwargs):允許函式接收任意數量的關鍵字參數。

聽到這麼多專有名詞,不用擔心,接下來會一一跟大家介紹這些參數的作用是什麼:

位置參數(Positional Arguments)


位置參數,顧名思義,你必須要以正確的順序來傳入函數,呼叫時的數量必須和你宣告的參數是一樣的。

如以下例子,呼叫 printme() 函數時,我們必須要傳入一個參數,否則會 error:

1
2
3
4
5
6
def printme(str):
print(str)
return

# 呼叫 printme() 函數,如果不傳入一個參數(因為函數裡面的參數只有一個,所以必須傳入一個)的話,會 error。
printme()

輸出結果:

1
2
3
4
Traceback (most recent call last):
File "test.py", line 10, in <module>
printme()
TypeError: printme() missing 1 required positional argument: 'str'

關鍵字參數(Keyword Arguments)


我們在使用關鍵字參數時,Python 允許函數呼叫時參數的順序與宣告時不一致(不受函數宣告的參數順序影響),因為 Python 直譯器能夠直接用參數名稱來匹配參數值。

如下列範例所示:

1
2
3
4
5
def printme(str):
print(str)
return

printme(str = "Hello World!")

可以看到當我們在呼叫 printme() 函數時,使用關鍵字參數的方法是直接指名參數名稱(str),且指定(賦值)字串 “Hello World!”。

由於上述範例只有一個參數,不夠明顯看出,當在使用關鍵字參數時,能夠不受函數宣告的參數順序影響之結果,所以我們來做以下範例:

1
2
3
4
5
6
def printinfo(name, age):
print("名字: ", name)
print("年齡: ", age)
return

printinfo(age=17, name="Handsome")

輸出結果:

1
2
名字:  Handsome
年齡: 17

默認參數(Default Arguments)


在呼叫函數時,若沒有直接傳遞參數,那麼將使用默認參數,這個默認參數會在函數宣告參數時使用,如下所示:

1
def fun(a=20, b=20)

我們將函數內的參數皆指定一個數值,即使用了默認參數。接下來我們來看一個呼叫函數時的範例:

1
2
3
4
5
6
7
8
def printinfo(name, age = 87 ):
print("名字: ", name)
print("年齡: ", age)
return

printinfo(age=17, name="Handsome" )
print ("------------------------")
printinfo(name="Handsome")

輸出結果:

1
2
3
4
5
名字:  Handsome
年齡: 17
------------------------
名字: Handsome
年齡: 87

由上述輸出結果跟程式碼來看,我們發現當第一次呼叫函數,與第二次呼叫函數時有所不同,原因就是使用了默認參數。

像是第一次呼叫函數 printme(),我們明確指定兩個參數的值,然而實際結果如我們所理想的一樣。

第二次呼叫函數時,我們並沒有設定 age 參數之值,所以 age 參數直接指定為函數預先宣告好的值,這就是默認參數。

可變位置參數(*args)


加了星號 * 的參數會以元組(tuple)的形式導入,存放所有未命名的變數參數。

1
2
3
4
5
6
def printinfo( arg1, *vartuple ):
print ("輸出: ")
print (arg1)
print (vartuple)

printinfo( 70, 60, 50 )

當我們在宣告參數時,可能需要一次宣告許多參數,這時候你就需要用到可變位置參數(*args)了,接下來再舉一個例子,可能會讓你比較清楚理解何謂可變位置參數:

1
2
3
4
5
6
7
def add(*args):
ans = 0
for i in args:
ans += i
return ans

add(1,2,3,4,5) # Ans: 15

由此例可見,可變位置參數能夠允許函數接收任意數量的位置參數,因此在呼叫時能夠輸入任意數量的參數,像是 1, 2, 3, 4, 5, …。

不過當我們在呼叫函數時,沒有將其指定參數,那麼他就是個空元組,不會發生任何 error。

字典(dict)

kwargs 這個參數就是比 args 多加一個星號 而已,然後變成 kwargs。與 args 不同的是,*kwargs 的型態是字典(dict),這個我們還沒教過,待會與各位稍微說明一下。

字典,在 Python 中是一種可變型態,且能夠儲存任意型態的物件。

字典中每一個鍵(key)值(value),key=>value,鍵值對用冒號 : 分割,每個鍵與值之對都以逗號分隔,整個字典都包括在大括號內 { },格式如下所示:

d = {key1 : value1, key2 : value2, key3 : value3 }

鍵(Key)、值(Value)在字典中成一對,所以稱為鍵值對。

注意:dict 是 Python 的關鍵字和內建函數,變數名稱不建議命名為 dict。

image

圖源:Python3-字典 | 菜鳥教程

鍵(Key)必須為獨一無二,無法重複,而值(Value)可重複,不受限。

至於值(Value)可以是任何的資料型態,但鍵(Key)一定是不可變的資料型態,如:字串(string)、數字(Number)等。

以下是一個範例:

tinydict = {'name' : 'Handsome', 'age' : '17', 'sex' : 'male'}

也可以這麼建立一個字典:

1
2
tinydict1 = { 'abc': 456 }
tinydict2 = { 'abc': 123, 98.6: 37 }

以下是創建一個空字典的範例:

1
2
3
4
5
6
7
8
9
10
11
# 使用大括號 {} 來創建空字典
emptyDict = {}

# 印出字典
print(emptyDict)

# 查看字典的數量
print("Length:", len(emptyDict))

# 查看型態
print(type(emptyDict))

輸出結果:

1
2
3
{}
Length: 0
<class 'dict'>

接下來是使用內建函數 dict() 創建字典:

1
2
3
4
5
6
7
8
9
10
emptyDict = dict()

# 印出字典
print(emptyDict)

# 查看字典的數量
print("Length:",len(emptyDict))

# 查看型態
print(type(emptyDict))

輸出結果:

1
2
3
{}
Length: 0
<class 'dict'>

存取字典內容


和我們在列表中所做的事情是一樣的,只不過在字典中是要直接輸入鍵(Key)的名稱而已,如下所示:

tinydict['Name']

這樣就能夠存取字典中鍵的值了。

以下是一個範例:

1
2
3
4
tinydict = {'Name': 'Handsome', 'Age': 17, 'Class': 'First'}

print ("tinydict['Name']: ", tinydict['Name'])
print ("tinydict['Age']: ", tinydict['Age'])

修改字典內容


我們可以在字典新增鍵值對來擴充字典內容,也可以更改鍵的值,如下所示:

1
2
3
4
5
6
7
8
tinydict = {'Name': 'HandSome', 'Age': 7, 'Class': 'First'}

tinydict['Age'] = 17 # 更新 Age
tinydict['School'] = "某某高中" #新增 School 鍵

print(tinydict) # 查看字典所有鍵值對
print("tinydict['Age']: ", tinydict['Age']) # 存取 Age 鍵的值
print("tinydict['School']: ", tinydict['School']) # 存取 School 鍵的值

輸出結果:

1
2
3
{'Name': 'HandSome', 'Age': 17, 'Class': 'First', 'School': '某某高中'}
tinydict['Age']: 17
tinydict['School']: 某某高中

刪除字典鍵值對


如要刪除一個字典,除去這個資料型態我們可以直接用 del 關鍵字來進行移除,不過也可以透過此關鍵字來對單一個鍵值對進行移除。

若我們只是想要移除字典裡面的所有鍵值對的話,則我們會使用 clear() 方法。

以下是一個範例:

1
2
3
4
5
tinydict = {'Name': 'Handsome', 'Age': 17, 'Class': 'First'}

del tinydict['Name'] # 刪除鍵 'Name'
tinydict.clear() # 清空字典
del tinydict # 刪除字典

字典鍵的特性


字典值(Value)可以是 Python 任意之物件,但鍵不行。

以下兩點請各位務必記住:

  1. 同一個鍵不被允許出現兩次。創建時如果同一個鍵被指定(賦值)兩次,後一個值會被記住,如下範例:
1
2
3
tinydict = {'Name': 'Handsome', 'Age': 7, 'Name': 'UglyMan'}

print ("tinydict['Name']: ", tinydict['Name'])

輸出結果:

1
tinydict['Name']:  UglyMan
  1. 鍵必須為不可變物件,所以可用數字(Number)、字串(String)、元組(Tuple)等不可變物件作為鍵,而我們使用列表(list)就不行。如下範例:
1
2
3
tinydict = {['Name']: 'Handsome', 'Age': 7}

print ("tinydict['Name']: ", tinydict['Name'])

輸出結果:

1
2
3
4
Traceback (most recent call last):
File "test.py", line 3, in <module>
tinydict = {['Name']: 'Runoob', 'Age': 7}
TypeError: unhashable type: 'list'

字典內建函數及方法(Functinos and Methods)


Number函數描述
1len(dict)計算字典元素總數,也就是字典的鍵之總數。
2str(dict)讓字典整體以字串形式表示,如:”{‘Name’: ‘Handsome’, ‘Class’: ‘First’, ‘Age’: 7}”。
3len(dict)計算字典元素總數,也就是字典的鍵之總數。
Number方法描述
1dict.clear()刪除字典內所有的元素(鍵值對)
2dict.copy()回傳一個字典的淺複製
3dict.fromkeys(seq [, value])建立一個新字典,以序列 seq 中所有元素做字典的鍵,val 為字典所有鍵對應的初始值,默認為 None
4dict.get(key, default=None)回傳指定鍵的值,如果鍵不在字典中傳回 default 設定的預設值 None
5key in dict如果鍵在字典 dict 裡回傳 true,否則回傳 false
6dict.setdefault(key, default=None)和get()類似,但如果鍵不存在於字典中,將會增加s鍵並將值設為default
7dict.update(dict2)把字典 dict2 的「鍵/值」對更新到 dict 裡
8pop(key [,default])刪除字典 key(鍵)所對應的值,回傳被刪除的值。
9popitem()回傳並刪除字典中的最後一對鍵和值。

註:上述方法仍有些未在表中列出,詳請可至 Python 3 字典 | 菜鳥教程 滑到最下面就有了。

可變關鍵字參數(**kwargs)

我們回到可變關鍵字參數(kwargs),前面說過,kwargs 與 args 型態是不同的,**kwargs 是使用字典(dict)作為資料型態,屬於可變物件,而 args 使用元組(tuple),是不可變物件。

**kwargs 允許函式接收任意數量的「關鍵字參數」,總之,我們來看以下範例:

1
2
3
4
5
6
def printinfo( arg1, **vardict ):
print ("輸出: ")
print (arg1)
print (vardict)

printinfo(1, a=2,b=3)

輸出結果:

1
2
3
輸出: 
1
{'a': 2, 'b': 3}

可以看到 a、b 各為鍵(Key),而 a 後面的 2 就是 a 這個鍵的值(Value),依此類推。

而當我們在宣告函數時,其實 * 星號是可以單獨出現在函數中參數的,例如:

1
2
def f(a,b,*,c):
return a+b+c

但如果單獨出現星號 ,則星號 後面的參數必須以關鍵字參數的形式輸入:

1
2
3
4
5
6
7
8
9
10
11
12
>>> def f(a,b,*,c):
... return a+b+c
...
>>> f(1,2,3) # Error

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() takes 2 positional arguments but 3 were given

>>> f(1,2,c=3) # 正常
6
>>>

總結

match…case


※註:match…case 這個功能只有在 Python 3.10 以上版本才有。

match…case 主要是用於簡化 if… else 的判斷,能夠使程式碼變得更加簡明扼要。

語法格式如下:

1
2
3
4
5
6
7
match expression:
case pattern1:
# 處理 pattern1 的邏輯
case pattern2 if condition:
# 處理 pattern2 並且滿足 condition 的邏輯
case _:
# 處理其他情況的邏輯

函式(function)


函式可稱為副程式、函數等中文名稱。

本篇主要說明了以下幾個性質:

  • 可重用性(Reusability)
  • 模組化(Modularity)
  • 封裝性(Encapsulation)
  • 輸入和輸出(I/O:Input and Output)
  • 抽象化(Abstraction)
  • 作用域(Scope)
  • 遞迴(Recursion)

關鍵字在 python 中為 def。

函式的命名規則與變數命名規則相同。

注意在名稱最後記得加上冒號。

參數是函式建立之初所預設就有的東西,用於輸入輸出之間的調味劑,如數學中的:f(x) = x^2 + x + 1,每一項都是屬於參數的範疇。

在 Python 中參數分為以下幾種:

  • 位置參數(Positional Arguments)
  • 關鍵字參數(Keyword Arguments)
  • 默認參數(Default Arguments)
  • 可變位置參數(*args)
  • 可變關鍵字參數(**kwargs)

字典(dict)


字典必須有鍵值「對」,鍵(key)與值(value)必須是一對。

字典顧名思義就是字典,我們常看的中翻英字典格式像這樣:「蘋果:Apple」,在 Python 中可這樣寫:

1
english_dictionary = {"蘋果" : "Apple"}

不過字典的值可以是任意資料型態;鍵必須是不可變物件(string、tuple 等)。

字典存取方式,以上述為例:english_dictionary[“蘋果”],會輸出 Apple。

以下是字典的內建函數及方法:

Number函數描述
1len(dict)計算字典元素總數,也就是字典的鍵之總數。
2str(dict)讓字典整體以字串形式表示,如:”{‘Name’: ‘Handsome’, ‘Class’: ‘First’, ‘Age’: 7}”。
3len(dict)計算字典元素總數,也就是字典的鍵之總數。
Number方法描述
1dict.clear()刪除字典內所有的元素(鍵值對)
2dict.copy()回傳一個字典的淺複製
3dict.fromkeys(seq [, value])建立一個新字典,以序列 seq 中所有元素做字典的鍵,val 為字典所有鍵對應的初始值,默認為 None
4dict.get(key, default=None)回傳指定鍵的值,如果鍵不在字典中傳回 default 設定的預設值 None
5key in dict如果鍵在字典 dict 裡回傳 true,否則回傳 false
6dict.setdefault(key, default=None)和get()類似,但如果鍵不存在於字典中,將會增加s鍵並將值設為default
7dict.update(dict2)把字典 dict2 的「鍵/值」對更新到 dict 裡
8pop(key [,default])刪除字典 key(鍵)所對應的值,回傳被刪除的值。
9popitem()回傳並刪除字典中的最後一對鍵和值。

好那以上就是本次教學的內容囉~接下來是一些參考資料:

參考資料

Python match…case 語句 | 菜鳥教程

Python3 函數 | 菜鳥教程

Python3 字典 | 菜鳥教程

設計看JS - Parameter & Argument - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

Python - 函式參數傳遞 - Alvin - Medium

Python match…case Statement (With Examples)

Python Function | Board Infinity