ICT 選修 EC4

子程式

Sub-programs · 模組化程式設計

第4章 Python 程式設計 6個核心主題 互動測驗 + 閃卡

本章內容

點擊任意卡片直接跳轉對應章節

子程式概念
模組化 · 函數類型
定義與語法
def · 形式參數 · 傳回值
變數範圍
局部變量 · 全程變量
傳遞參數
不可變 · 可變物件
程式存根
測試 · 除錯
互動測驗
12題 · 即時評分
3D 閃卡
20張 · 翻轉記憶
歷屆試題
分難度 · 參考答案
詞彙表
中英對照

子程式概念

了解模組化設計的核心理念及子程式的四種類型

模組化 (Modularisation)

將複雜問題分解為多個較小、可管理的子問題(模組),逐一處理。在程式設計中,這些模組稱為子程式(在 Python 中稱為函數 function)。每個子程式代表多行程式碼,可以獨立使用,也可以重複呼叫。

模組化的好處
  • 易於理解 (Easy to understand) — 程式結構清晰,易於閱讀和維護
  • 促進重用 (Facilitate reuse) — 子程式可在不同地方重複使用,避免重複撰寫相同程式碼
  • 提高開發效率 (Enhance development efficiency) — 多人可分工撰寫不同子程式,提升協作效率

子程式的四種類型

1. 無輸入、無輸出

沒有輸入參數,也沒有傳回值。通常執行預設程式碼,例如在 Shell 中列印資訊。

def printSomething(): print("Hello") print("Welcome!")

2. 有輸入、無輸出

有輸入參數但沒有傳回值。對參數進行運算,但不以傳回值形式返回結果。

def printList(numList): print(numList)

3. 無輸入、有輸出

沒有輸入參數,但有傳回值。可以直接使用程式中的變數進行運算,例如隨機數生成器。

def luckyDraw(): return random.choice(names)

4. 有輸入、有輸出

最常見的類型。有輸入參數和傳回值,通常以參數形式傳入數值,並以傳回值形式返回運算結果。

def sum(a, b): return a + b

呼叫子程式 (4.2)

內置函數

Python 提供許多常用的內置函數:

函數描述
abs(x)傳回 x 的絕對值
round(x, y)將 x 四捨五入至 y 位小數
print()輸出至 Shell
input()從用戶讀取輸入
int()轉換為整數
數學函數庫 (math)

需要先 import math 才能使用:

函數說明
math.sqrt(x)計算 x 的平方根
math.sin(x)計算 x 弧度的正弦值
math.cos(x)計算 x 弧度的餘弦值
math.exp(x)計算自然指數函數 $e^x$
隨機函數庫 (random)

需要先 import random 才能使用:

函數說明
random.random()傳回 0 至 1(不含)的隨機浮點數
random.uniform(a,b)傳回 a 至 b(不含)的隨機浮點數
random.randint(a,b)傳回 a 至 b 的隨機整數

定義子程式

學習如何在 Python 中使用 def 關鍵字定義子程式

基本語法結構

每個子程式在被呼叫之前必須先定義。在 Python 中,使用關鍵字 def 來定義子程式:

def myFunction(p1, p2, p3, ...): # Statement 1 ← 縮排 (Indentation) # Statement 2 標示哪些語句屬於此子程式 # Statement 3 # ... value = "return something" return value ← 傳回值 (Return value)
子程式命名規則
  • 名稱是其識別符 (identifier)
  • 同一程式中每個識別符必須唯一,不允許重複
  • 命名規則與變數命名規則相同
  • 名稱應反映其實際用途,以提高可讀性
形式參數 (Formal Parameters)

在括號內列出要傳入子程式的參數。多個參數用逗號分隔;無參數則留空括號。

def myFunctionA(a): # 1個參數 def myFunctionB(a, b, c): # 多個參數 def myFunctionC(): # 無參數
傳回值 (Return Value)

return 關鍵字結束子程式呼叫並將資料傳回呼叫位置。可傳回一個或多個值。若無需傳回值,則不需要 return。

return value1 # 傳回一個值 return value1, value2 # 傳回多個值

完整範例:add3(a, b, c)

def add3(a, b, c): # a, b, c 是形式參數 (formal parameters) s = a + b + c # 主體:計算三個參數之和 return s # s 是傳回值 (return value) # 呼叫 (Calling) 子程式: n1 = 1 n2 = 2 n3 = 3 summ = add3(n1, n2, n3) # 傳回值 6 print(summ) # 輸出: 6 n4 = 4 n5 = 5 summ = add3(summ, n4, n5) # 傳回值 15 print(summ) # 輸出: 15

實際參數 (actual parameters) 也稱為變元 (arguments),即傳入函數的值。子程式必須在被呼叫前定義,否則會出現 NameError。

變數範圍

了解局部變量與全程變量的區別及使用方法

局部變量 (Local Variable)

在子程式內宣告的變數。只在該子程式內有效;子程式結束後,所有局部變量將被銷毀。形式參數也屬於局部變量。

def add(a, b): result = a + b # result 是局部變量 print(result) def sub(a, b): result = a - b # 不同子程式的 result 是不同變數! print(result)
全程變量 (Global Variable)

在子程式外宣告的變數。其範圍涵蓋整個程式,包括所有子程式。在子程式內可讀取全程變量的值;若要修改其值,必須使用 global 關鍵字。

score = 0 # 全程變量 def add1(): global score # 宣告使用全程變量 score = score + 1 add1() print(score) # 輸出: 1
常見錯誤:

若在子程式內未使用 global 關鍵字就嘗試修改全程變量,Python 會將其視為一個新的局部變量,從而產生錯誤(UnboundLocalError)。

類比:香港計程車有三種:紅色(市區)、綠色(新界)、藍色(大嶼山)。全程變量就像紅色計程車,可在全港行駛;局部變量就像綠色或藍色計程車,只能在特定區域行駛。

傳遞參數

Python 根據實際參數的資料類型決定傳遞方式

傳遞不可變物件 (Immutable)

整數 (int)、浮點數 (float)、布林值 (bool)、字串 (str) 是不可變物件。

傳入不可變物件時,實際參數的值會被複製到形式參數。子程式內對形式參數的修改不會影響實際參數的值。

def add(x): x = x + 1 # 修改局部副本 num = 1 add(num) print(num) # 仍輸出: 1(未改變)
傳遞可變物件 (Mutable)

列表 (list) 是可變物件。

傳入可變物件時,形式參數儲存實際參數的記憶體位址(指示標 pointer)。子程式內對形式參數的修改會直接反映在實際參數上。

def add(x): x[0] = x[0] + 1 # 修改原始列表 num = [1] add(num) print(num) # 輸出: [2](已改變!)
實際參數的資料類型 物件類型 對實際參數的影響
int, float, bool, str 不可變物件 不影響 (複製傳遞)
list 可變物件 會影響 (參考傳遞)

增強知識:在 C++ 中,這兩種傳遞方式分別稱為「按值調用 (call-by-value)」和「按址調用 (call-by-reference)」。Python 的行為與 C++ 類似,但由資料類型自動決定。

程式存根 (Stubs)

使用存根來測試和除錯複雜的模組化程式

什麼是存根?

存根是用簡短、臨時的程式碼代替子程式主體,讓主程式即使在子程式未完成時也能運行。由於存根是簡單程式碼,幾乎不含語法或邏輯錯誤,因此可以縮小檢查範圍,更有效地定位問題。

無傳回值的存根
def stubs_with_no_return_value(): print() # 簡單的佔位程式碼
有傳回值的存根
def stubs_with_return_value(): return 100 # 可根據傳回值資料類型修改
BMI 計算範例

假設主程式包含三個子程式:計算BMI、分析BMI、製作報告。在測試「製作報告」子程式時,可用存根替代前兩個子程式:

# 存根替代「計算BMI」 def calculateBMI(): bmi = 21 # 固定值存根 # 存根替代「分析BMI」 def analyseBMI(): category = "Normal" # 固定值存根 # 正在測試的子程式 def makeReport(): report = "Your BMI: " + str(bmi) + " belongs to " + category return report
4
子程式類型
3
模組化好處
2
變數範圍類型
2
參數傳遞方式

知識測驗

測試你對子程式的掌握程度,共 12 題,即時評分

題目 1 / 12
得分:0
題目 1 / 12
以下哪個是模組化設計的好處?
題目 2 / 12
在 Python 中,定義子程式使用哪個關鍵字?
題目 3 / 12
以下程式碼的輸出是什麼?
def add3(a, b, c): s = a + b + c return s print(add3(1, 2, 3))
題目 4 / 12
在子程式內宣告的變數稱為什麼?
題目 5 / 12
以下哪種資料類型是可變物件 (mutable object)?
題目 6 / 12
使用 random.randint(1, 10) 可能返回哪些值?
題目 7 / 12
若要在子程式內修改全程變量,需要使用哪個關鍵字?
題目 8 / 12
程式存根 (stub) 的主要用途是什麼?
題目 9 / 12
以下程式碼執行後,num 的值是多少?
def add(x): x = x + 1 num = 5 add(num) print(num)
題目 10 / 12
math.sqrt(16) 的返回值是什麼?
題目 11 / 12
以下程式碼的輸出是什麼?
def add(x): x[0] = x[0] + 1 num = [5] add(num) print(num)
題目 12 / 12
形式參數 (formal parameters) 屬於哪種類型的變數?
0/12
你的得分

3D 閃卡

點擊卡片翻轉查看解釋,鞏固關鍵概念

1 / 20
點擊查看解釋
Sub-program / Function
解釋
A module broken down from a program that can be used independently and repeatedly. Called a function in Python. 從程式分解出來的模組,可獨立且重複使用。在 Python 中稱為函數。

試題練習

根據教材整理的典型考試題目,附參考答案

基礎 Checkpoint 4.1 Q1
Mr Lee 設計了一個分析數學考試成績的程式。他使用陣列 mark 儲存 10 名學生的成績:[78, 89, 87, 95, 60, 44, 51, 98, 77, 69]。其中一個子程式是 average(),它返回學生的平均成績。請問呼叫 average() 的傳回值是什麼?
參考答案: 72.8

解析: 計算平均值:(78+89+87+95+60+44+51+98+77+69) ÷ 10 = 728 ÷ 10 = 72.8
基礎 Checkpoint 4.1 Q1(b)
另一個子程式 higher(m) 返回成績高於 m 的學生人數。請問呼叫 higher(90) 的傳回值是什麼?(使用上題的成績陣列)
參考答案: 2

解析: 成績高於 90 的學生:95 和 98,共 2 人。
中等 Checkpoint 4.1 Q2
Davis 負責編寫一個子程式 functionA(a, b),該子程式要求用戶輸入兩個整數 a 和 b,然後返回它們的差值。例如,functionA(6, 2) 返回 4,functionA(3, 9) 返回 6。請問呼叫 functionA(5, 10) 的傳回值是什麼?
參考答案: 5

解析: 根據題目規律,functionA(a, b) 返回 |a - b|(絕對差值)。functionA(5, 10) = |5 - 10| = 5。
中等 Chapter Exercise Q3
Yannis 使用陣列 Z 儲存十二生肖,並編寫子程式 zodiac(year) 返回給定年份對應的生肖。提示:將年份減去 4 後除以 12,餘數為 0 時生肖為「鼠」,餘數為 1 時為「牛」,依此類推。請問呼叫 zodiac(2013) 的傳回值是什麼?
參考答案: 蛇 (snake)

計算步驟:
(2013 - 4) ÷ 12 = 2009 ÷ 12 = 167 餘 5。餘數 5 對應生肖:鼠(0)→牛(1)→虎(2)→兔(3)→龍(4)→蛇(5)。因此答案是「蛇」。
困難 Chapter Exercise Q4
十六進制數制以 16 為基數,使用數字 0-9 和字母 A-F(A-F 分別等於 10-15)。Bosco 嘗試編寫子程式 hex2dec(h) 將十六進制字串轉換為十進制數。偽代碼如下:

Sub-program hex2dec(h) dec ← 0 length ← length of string h for i from 0 to ________ ... return dec
(i) 循環範圍應填什麼?
(ii) 變數 dec 屬於哪種類型的變數?
參考答案:
(i) for i from 0 to length - 1(即遍歷字串的每個字元,索引從 0 到 length-1)
(ii) dec 是局部變量 (local variable),因為它在子程式 hex2dec(h) 內部宣告,只在該子程式內有效。
困難 Chapter Exercise Q2
Tim 使用二維陣列 image 儲存點陣圖影像。他編寫子程式 avg(i, j) 計算並返回 image[i,j] 至 image[i+1,j+1] 的平均值。請完成偽代碼:
Sub-program avg(i, j) average ← ________ for x from ________ to ________ for y from ________ to ________ average ← average + image[y,x] return ________
參考答案:
Sub-program avg(i, j) average ← 0 for x from i to i+1 for y from j to j+1 average ← average + image[y,x] return average / 4
解析: 需要遍歷 2×2 的區域(共 4 個元素),累加後除以 4 得到平均值。

中英詞彙對照

本章所有重要術語的中英文對照及定義

sub-program
子程式
從程式分解出來的模組,可獨立且重複使用
function
函數
Python 中子程式的稱呼
modularisation
模組化
將複雜問題分解為較小模組的設計方法
calling sub-program
調用子程式
透過名稱和實際參數執行子程式
formal parameter
形式參數
定義子程式時括號內列出的參數
actual parameter
實際參數
呼叫子程式時傳入的實際值,也稱變元
argument
變元
實際參數的另一種稱呼
return value
傳回值
子程式執行後傳回給呼叫位置的資料
identifier
識別符
程式中變數或子程式的唯一名稱
built-in function
內置函數
Python 預先提供的函數,無需定義即可使用
library
函數庫
包含多個相關函數的集合,需要 import 後使用
scope
範圍
變數可以被使用的程式區域
local variable
局部變量
在子程式內宣告的變數,只在該子程式內有效
global variable
全程變量
在子程式外宣告的變數,範圍涵蓋整個程式
passing parameter
傳遞參數
呼叫子程式時將實際參數傳給形式參數的過程
immutable object
不可變的物件
int, float, bool, str — 傳遞時複製值,不影響原始變數
mutable object
可變的物件
list — 傳遞時傳遞記憶體位址,修改會影響原始變數
pointer
指示標
儲存記憶體位址的變數
stub
子程式存根
用簡短臨時程式碼代替子程式,用於測試和除錯

EC4 Sub-programs 互動學習頁面 | 資訊及通訊科技 選修課程