B3: 複雜工程學:函式、模組化與作用域
任務背景
在木星軌道站,你需要管理多個複雜的子系統:生命維持、能源管理、通訊系統等。如果將所有邏輯寫在一個巨大的程式中,維護將是噩夢!
作為系統工程師,你需要學會將複雜問題分解為多個獨立的模組(函式),每個模組負責一個明確的任務。這不僅讓程式更易於理解和除錯,也能讓程式碼重複使用。
在這個訓練模組中,你將學習:- 如何定義和使用函式
- 理解變數的作用域(Scope)
- 掌握 Python 的參數傳遞機制
- 函式的最佳實踐
知識點說明
為什麼需要函式?
問題分解(Problem Decomposition):將一個複雜問題拆解成多個更小、更易於管理的子問題。# ❌ 不好的做法:所有邏輯混在一起
data = input()
# ... 100 行程式碼 ...
result = ...
print(result)
# ✅ 好的做法:模組化
def parse_data(raw_data):
"""解析輸入數據"""
return processed_data
def calculate(data):
"""執行計算"""
return result
def format_output(result):
"""格式化輸出"""
return formatted
# 主程式清晰易讀
data = parse_data(input())
result = calculate(data)
print(format_output(result))
函式定義語法
def function_name(parameter1, parameter2):
"""
函式說明文件(Docstring)
"""
# 函式主體
result = parameter1 + parameter2
return result # 回傳值
作用域(Scope)
區域變數 vs 全域變數:global_var = 100 # 全域變數
def my_function():
local_var = 50 # 區域變數
print(global_var) # 可以讀取全域變數
print(local_var) # 可以讀取區域變數
my_function()
# print(local_var) # ❌ 錯誤!無法在函式外存取區域變數
⚠️ 最佳實踐:盡量避免使用全域變數,通過參數傳遞和回傳值來溝通。
Python 的參數傳遞機制
Python 使用「物件參考傳遞」(Call by Object Reference):
可變物件(Mutable):def modify_list(lst):
lst.append(999) # 會修改原始列表
my_list = [1, 2, 3]
modify_list(my_list)
print(my_list) # [1, 2, 3, 999] ✓ 被修改了
不可變物件(Immutable):
def modify_number(n):
n = n + 100 # 創建新物件,不影響原始變數
my_num = 50
modify_number(my_num)
print(my_num) # 50 ✓ 沒有被修改
範例程式碼
範例 1:計算火箭燃料消耗
import sys
def calculate_fuel(distance, efficiency):
"""
計算所需燃料
distance: 飛行距離(公里)
efficiency: 燃料效率(公里/公升)
"""
fuel_needed = distance / efficiency
return fuel_needed
def format_report(distance, fuel):
"""格式化報告"""
return f"飛行 {distance} 公里需要 {fuel:.2f} 公升燃料"
# 主程式
distance = int(sys.stdin.readline())
efficiency = float(sys.stdin.readline())
fuel = calculate_fuel(distance, efficiency)
print(format_report(distance, fuel))
輸入範例:
1000
25.5
輸出範例:
飛行 1000 公里需要 39.22 公升燃料
範例 2:溫度轉換系統
import sys
def celsius_to_fahrenheit(celsius):
"""攝氏轉華氏"""
return celsius * 9/5 + 32
def fahrenheit_to_celsius(fahrenheit):
"""華氏轉攝氏"""
return (fahrenheit - 32) * 5/9
def kelvin_to_celsius(kelvin):
"""克耳文轉攝氏"""
return kelvin - 273.15
# 讀取溫度和單位
temp = float(sys.stdin.readline())
unit = sys.stdin.readline().strip()
if unit == 'C':
print(f"{celsius_to_fahrenheit(temp):.2f} °F")
elif unit == 'F':
print(f"{fahrenheit_to_celsius(temp):.2f} °C")
elif unit == 'K':
print(f"{kelvin_to_celsius(temp):.2f} °C")
範例 3:質數檢測
import sys
def is_prime(n):
"""
檢查 n 是否為質數
回傳 True 或 False
"""
if n < 2:
return False
if n == 2:
return True
if n % 2 == 0:
return False
# 只需檢查到 sqrt(n)
i = 3
while i * i <= n:
if n % i == 0:
return False
i += 2
return True
# 主程式
n = int(sys.stdin.readline())
if is_prime(n):
print(f"{n} 是質數")
else:
print(f"{n} 不是質數")
範例 4:列表統計函式
import sys
def calculate_stats(numbers):
"""
計算列表的統計數據
回傳:(總和, 平均值, 最大值, 最小值)
"""
total = sum(numbers)
avg = total / len(numbers)
maximum = max(numbers)
minimum = min(numbers)
return total, avg, maximum, minimum
# 讀取數據
n = int(sys.stdin.readline())
numbers = list(map(int, sys.stdin.readline().split()))
# 呼叫函式並解包回傳值
total, avg, maximum, minimum = calculate_stats(numbers)
print(f"總和:{total}")
print(f"平均:{avg:.2f}")
print(f"最大:{maximum}")
print(f"最小:{minimum}")
程式碼解說
關鍵技術點
#### 1. 函式設計原則
單一職責原則(Single Responsibility Principle):- 每個函式只做一件事
- 函式名稱應清楚描述其功能
- 函式長度建議不超過 20-30 行
#### 2. 參數與回傳值
def process_data(input_data, option=True):
"""
input_data: 必要參數
option: 選擇性參數(有預設值)
"""
if option:
return input_data * 2
return input_data
#### 3. 多個回傳值
Python 可以回傳多個值(實際上是回傳一個 tuple):
def get_min_max(numbers):
return min(numbers), max(numbers)
minimum, maximum = get_min_max([1, 5, 3, 9, 2])
#### 4. 遞迴初探
函式可以呼叫自己:
def factorial(n):
"""計算階乘"""
if n <= 1: # 基礎情況
return 1
return n * factorial(n - 1) # 遞迴呼叫
Quiz: 太空站系統管理
題目
木星軌道站需要一個氧氣管理系統。請設計以下函式:
calculate_oxygen_consumption(crew_size, days)- 計算氧氣消耗量- 每人每天消耗 0.84 公斤氧氣
check_oxygen_level(current, required)- 檢查氧氣是否足夠- 回傳 True(足夠)或 False(不足)
format_warning(shortage)- 格式化警告訊息- 如果短缺,回傳警告訊息
第一行:機組人員數量
第二行:任務天數
第三行:當前氧氣儲量(公斤)
輸出格式:
- 如果足夠:
氧氣充足:剩餘 X.XX 公斤 - 如果不足:
警告:氧氣短缺 X.XX 公斤!
5
30
100
輸出範例:
警告:氧氣短缺 26.00 公斤!
Quiz 解答
import sys
def calculate_oxygen_consumption(crew_size, days):
"""計算氧氣消耗量"""
consumption_per_person_per_day = 0.84
total_consumption = crew_size days consumption_per_person_per_day
return total_consumption
def check_oxygen_level(current, required):
"""檢查氧氣是否足夠"""
return current >= required
def format_warning(shortage):
"""格式化警告訊息"""
if shortage < 0:
return f"警告:氧氣短缺 {abs(shortage):.2f} 公斤!"
else:
return f"氧氣充足:剩餘 {shortage:.2f} 公斤"
# 主程式
crew_size = int(sys.stdin.readline())
days = int(sys.stdin.readline())
current_oxygen = float(sys.stdin.readline())
# 計算所需氧氣
required = calculate_oxygen_consumption(crew_size, days)
# 計算剩餘或短缺
difference = current_oxygen - required
# 輸出結果
print(format_warning(difference))
解答說明
模組化設計的優勢:- 易於測試:每個函式可以獨立測試
- 易於維護:修改某個功能只需改對應函式
- 易於重用:函式可以在不同地方使用
- 易於理解:主程式邏輯清晰
- 使用動詞開頭:
calculate_,check_,format_ - 名稱描述功能:一看就知道做什麼
訓練完成!
恭喜你完成 函式與模組化工程 訓練!