學習目標
- • 了解 Python 的特色和應用領域
- • 掌握變數宣告和基本資料型別
- • 學會使用運算子進行計算和比較
- • 掌握輸入輸出和字串處理
- • 學會條件判斷和迴圈控制
- • 了解串列、字典等資料結構
- • 學會定義和使用函數
- • 能夠編寫完整的 Python 程式
第1課:Python 簡介與第一個程式
基礎了解什麼是 Python,為什麼它是最適合初學者的程式語言,並寫出你的第一個程式。
什麼是 Python?
Python 是一種高階程式語言,由 Guido van Rossum 在 1991 年創造。它的名字來自英國喜劇團體「Monty Python」。
為什麼選擇 Python?
- 簡單易學:語法接近自然語言,容易理解
- 功能強大:可以做很多事情,從網站到人工智慧
- 社群活躍:有很多人使用,容易找到幫助
- 免費開源:完全免費使用
你的第一個 Python 程式:
# 這是註解,電腦會忽略這行
# 你的第一個 Python 程式
print("Hello, World!")
print("歡迎來到 Python 的世界!")
print("我正在學習程式設計")
程式碼解釋:
- # 註解:以 # 開頭的是註解,用來解釋程式碼,電腦會忽略
- print():這是一個函數,用來在螢幕上顯示文字
- 引號:文字要放在引號裡面,可以用單引號 ' 或雙引號 "
- 括號:函數後面要加括號,要顯示的內容放在括號裡
每一行程式碼就是一個指令,電腦會從上到下依序執行。
💡 實作練習
試著修改上面的程式碼,讓它顯示你的名字和你想說的話!
Python 的應用領域:
🌐 網頁開發
Instagram、YouTube 都使用 Python
🤖 人工智慧
機器學習、深度學習
📊 資料科學
資料分析、視覺化
🔧 自動化
自動處理重複性工作
第2課:變數與資料型別
基礎學習如何使用變數來儲存資料,以及 Python 中的基本資料型別。
什麼是變數?
變數就像是一個盒子,可以用來儲存資料。你可以給這個盒子取一個名字,然後把東西放進去,之後就可以用這個名字來取出裡面的東西。
在 Python 中,建立變數非常簡單,只要用 =
符號就可以了:
基本變數宣告:
# 字串 (文字)
name = "小明"
city = "台北"
message = "Hello, World!"
# 整數 (沒有小數點的數字)
age = 25
score = 100
year = 2024
# 浮點數 (有小數點的數字)
height = 175.5
weight = 65.2
temperature = 36.5
# 布林值 (True 或 False)
is_student = True
is_raining = False
has_license = True
# 顯示變數內容
print("姓名:", name)
print("年齡:", age)
print("身高:", height)
print("是學生:", is_student)
資料型別詳解:
🔤 字串 (str)
用來儲存文字,要用引號包起來
"Hello" 或 'Hello'
🔢 整數 (int)
沒有小數點的數字
42, -10, 0
🔢 浮點數 (float)
有小數點的數字
3.14, -2.5, 0.0
✅ 布林值 (bool)
只有兩個值:True 或 False
True, False
變數命名規則:
- 只能包含字母、數字和底線 (_)
- 不能以數字開頭
- 不能使用 Python 的關鍵字 (如 if, for, while 等)
- 建議使用有意義的名字
✅ 好的變數名: name, age, student_count, is_valid
❌ 不好的變數名: 1name, if, a, x123
檢查資料型別:
# 使用 type() 函數檢查資料型別
name = "小明"
age = 25
height = 175.5
is_student = True
print(type(name)) #
print(type(age)) #
print(type(height)) #
print(type(is_student)) #
# 更友善的顯示方式
print(f"name 的型別是: {type(name).__name__}")
print(f"age 的型別是: {type(age).__name__}")
print(f"height 的型別是: {type(height).__name__}")
print(f"is_student 的型別是: {type(is_student).__name__}")
💡 實作練習
建立變數來儲存你的個人資訊:姓名、年齡、身高、是否為學生,然後用 print() 顯示出來!
第3課:運算子與表達式
基礎學習如何使用各種運算子進行計算、比較和邏輯運算。
算術運算子:
# 基本算術運算
a = 10
b = 3
print(f"{a} + {b} = {a + b}") # 加法:13
print(f"{a} - {b} = {a - b}") # 減法:7
print(f"{a} * {b} = {a * b}") # 乘法:30
print(f"{a} / {b} = {a / b}") # 除法:3.333...
print(f"{a} // {b} = {a // b}") # 整數除法:3
print(f"{a} % {b} = {a % b}") # 餘數:1
print(f"{a} ** {b} = {a ** b}") # 次方:1000
# 實際應用範例
price = 100
discount = 0.2 # 20% 折扣
final_price = price * (1 - discount)
print(f"原價:{price},折扣後:{final_price}")
比較運算子:
# 比較運算子
x = 5
y = 10
print(f"{x} == {y}: {x == y}") # 等於:False
print(f"{x} != {y}: {x != y}") # 不等於:True
print(f"{x} > {y}: {x > y}") # 大於:False
print(f"{x} < {y}: {x < y}") # 小於:True
print(f"{x} >= {y}: {x >= y}") # 大於等於:False
print(f"{x} <= {y}: {x <= y}") # 小於等於:True
# 字串比較
name1 = "Alice"
name2 = "Bob"
print(f"'{name1}' == '{name2}': {name1 == name2}") # False
# 比較的結果是布林值
age = 18
is_adult = age >= 18
print(f"是否成年:{is_adult}") # True
邏輯運算子:
# 邏輯運算子
age = 20
has_license = True
has_car = False
# and:兩個條件都要為 True
can_drive = age >= 18 and has_license
print(f"可以開車:{can_drive}") # True
# or:至少一個條件為 True
has_transport = has_license or has_car
print(f"有交通工具:{has_transport}") # True
# not:反轉布林值
is_minor = not (age >= 18)
print(f"是未成年:{is_minor}") # False
# 複雜的邏輯組合
weather = "sunny"
temperature = 25
is_good_weather = weather == "sunny" and temperature > 20
print(f"天氣好:{is_good_weather}") # True
運算子優先順序:
Python 運算子的優先順序(由高到低):
- 括號 () - 最高優先權
- 次方 **
- 乘法 *、除法 /、整數除法 //、餘數 %
- 加法 +、減法 -
- 比較運算子 ==、!=、>、<、>=、<=
- 邏輯運算子 not
- 邏輯運算子 and
- 邏輯運算子 or - 最低優先權
實用範例:
# 計算 BMI
height = 1.75 # 公尺
weight = 70 # 公斤
bmi = weight / (height ** 2)
print(f"BMI: {bmi:.2f}")
# 判斷是否為偶數
number = 8
is_even = number % 2 == 0
print(f"{number} 是偶數:{is_even}")
# 計算圓的面積
import math
radius = 5
area = math.pi * radius ** 2
print(f"半徑 {radius} 的圓面積:{area:.2f}")
# 溫度轉換
celsius = 25
fahrenheit = celsius * 9/5 + 32
print(f"{celsius}°C = {fahrenheit}°F")
💡 實作練習
試著寫一個程式計算兩個數字的所有算術運算結果,並比較它們的大小關係!
第4課:輸入與輸出
中級學習如何從使用者獲取輸入,以及如何格式化輸出。
使用者輸入 - input():
# 基本輸入
name = input("請輸入你的姓名:")
print(f"你好,{name}!")
# 輸入數字(需要轉換型別)
age_str = input("請輸入你的年齡:")
age = int(age_str) # 轉換為整數
print(f"你今年 {age} 歲")
# 簡化寫法
age = int(input("請輸入你的年齡:"))
height = float(input("請輸入你的身高(公尺):"))
print(f"你今年 {age} 歲,身高 {height} 公尺")
# 輸入多個值
full_name = input("請輸入姓名(姓 名):")
first_name, last_name = full_name.split()
print(f"姓:{first_name},名:{last_name}")
格式化輸出:
# f-string 格式化(推薦)
name = "小明"
age = 25
score = 87.5
print(f"姓名:{name}")
print(f"年齡:{age}")
print(f"成績:{score}")
# 數字格式化
pi = 3.14159
print(f"圓周率:{pi:.2f}") # 保留2位小數:3.14
print(f"圓周率:{pi:.4f}") # 保留4位小數:3.1416
# 百分比格式
percentage = 0.875
print(f"正確率:{percentage:.1%}") # 87.5%
# 對齊格式
print(f"{'姓名':<10}{'年齡':<5}{'成績':<8}")
print(f"{'小明':<10}{25:<5}{87.5:<8}")
print(f"{'王小華':<10}{23:<5}{92.3:<8}")
# 其他格式化方法
print("姓名:{},年齡:{}".format(name, age))
print("姓名:%s,年齡:%d" % (name, age))
實用範例:
# 簡單計算機
print("=== 簡單計算機 ===")
num1 = float(input("請輸入第一個數字:"))
operator = input("請輸入運算符號(+, -, *, /):")
num2 = float(input("請輸入第二個數字:"))
if operator == "+":
result = num1 + num2
elif operator == "-":
result = num1 - num2
elif operator == "*":
result = num1 * num2
elif operator == "/":
if num2 != 0:
result = num1 / num2
else:
result = "錯誤:不能除以零"
else:
result = "錯誤:無效的運算符號"
print(f"{num1} {operator} {num2} = {result}")
# BMI 計算器
print("\n=== BMI 計算器 ===")
weight = float(input("請輸入體重(公斤):"))
height = float(input("請輸入身高(公尺):"))
bmi = weight / (height ** 2)
print(f"你的 BMI 是:{bmi:.2f}")
if bmi < 18.5:
category = "體重過輕"
elif bmi < 24:
category = "正常範圍"
elif bmi < 27:
category = "過重"
else:
category = "肥胖"
print(f"BMI 分類:{category}")
💡 實作練習
寫一個程式詢問使用者的姓名、年齡和興趣,然後用漂亮的格式顯示這些資訊!
第5課:條件判斷 (if/elif/else)
中級學習如何讓程式根據不同條件執行不同的動作。
基本 if 語句:
# 基本 if 語句
age = 18
if age >= 18:
print("你已經成年了!")
print("可以投票了")
# if-else 語句
weather = "sunny"
if weather == "sunny":
print("今天天氣很好,適合出門")
else:
print("今天天氣不太好")
# 多重條件 if-elif-else
score = 85
if score >= 90:
grade = "A"
print("優秀!")
elif score >= 80:
grade = "B"
print("良好!")
elif score >= 70:
grade = "C"
print("及格")
elif score >= 60:
grade = "D"
print("勉強及格")
else:
grade = "F"
print("不及格,需要加油")
print(f"你的等級是:{grade}")
巢狀條件判斷:
# 巢狀條件判斷
age = 20
has_license = True
has_car = False
if age >= 18:
print("你已經成年")
if has_license:
print("你有駕照")
if has_car:
print("你可以開自己的車")
else:
print("你可以租車或借車")
else:
print("你需要先考駕照")
else:
print("你還未成年,不能開車")
# 複雜的邏輯判斷
temperature = 25
humidity = 60
wind_speed = 5
if temperature > 20:
if humidity < 70:
if wind_speed < 10:
print("天氣很舒適")
else:
print("有點風,但還不錯")
else:
print("有點悶熱")
else:
print("有點涼")
實用範例:
# 密碼強度檢查
password = input("請輸入密碼:")
length = len(password)
has_upper = any(c.isupper() for c in password)
has_lower = any(c.islower() for c in password)
has_digit = any(c.isdigit() for c in password)
print("密碼強度分析:")
if length < 6:
print("❌ 密碼太短(至少6個字元)")
elif length < 8:
print("⚠️ 密碼長度一般")
else:
print("✅ 密碼長度足夠")
if has_upper and has_lower and has_digit:
print("✅ 密碼包含大小寫字母和數字")
strength = "強"
elif (has_upper and has_lower) or (has_lower and has_digit):
print("⚠️ 密碼還可以更強")
strength = "中等"
else:
print("❌ 密碼太簡單")
strength = "弱"
print(f"整體強度:{strength}")
# 簡單的遊戲:猜數字
import random
secret_number = random.randint(1, 10)
guess = int(input("猜一個1到10之間的數字:"))
if guess == secret_number:
print("🎉 恭喜你猜對了!")
elif abs(guess - secret_number) == 1:
print("😊 很接近了!")
else:
print("😔 猜錯了")
print(f"正確答案是:{secret_number}")
💡 實作練習
寫一個程式判斷一個年份是否為閏年(能被4整除但不能被100整除,或者能被400整除)!
第6課:迴圈 (for/while)
進階學習如何使用迴圈來重複執行程式碼,提高程式效率。
for 迴圈:
# 基本 for 迴圈
print("數數字:")
for i in range(5):
print(f"第 {i+1} 次")
# range() 的不同用法
print("\n從1到10:")
for num in range(1, 11):
print(num, end=" ")
print("\n\n偶數:")
for num in range(0, 11, 2): # 從0到10,每次增加2
print(num, end=" ")
# 遍歷字串
print("\n\n遍歷字串:")
word = "Python"
for letter in word:
print(f"字母:{letter}")
# 遍歷列表
print("\n遍歷列表:")
fruits = ["蘋果", "香蕉", "橘子"]
for fruit in fruits:
print(f"我喜歡吃{fruit}")
# 使用 enumerate 獲取索引
print("\n帶索引的遍歷:")
for index, fruit in enumerate(fruits):
print(f"{index+1}. {fruit}")
while 迴圈:
# 基本 while 迴圈
count = 1
while count <= 5:
print(f"計數:{count}")
count += 1 # 等同於 count = count + 1
# 使用者輸入驗證
print("\n密碼驗證:")
password = ""
while password != "123456":
password = input("請輸入密碼:")
if password != "123456":
print("密碼錯誤,請重試")
print("密碼正確!")
# 累加計算
print("\n計算1到100的總和:")
total = 0
num = 1
while num <= 100:
total += num
num += 1
print(f"1到100的總和是:{total}")
# 無限迴圈(小心使用)
print("\n簡單選單:")
while True:
choice = input("選擇操作 (1:問候, 2:時間, q:退出):")
if choice == "1":
print("你好!")
elif choice == "2":
import datetime
print(f"現在時間:{datetime.datetime.now()}")
elif choice == "q":
print("再見!")
break # 跳出迴圈
else:
print("無效選擇")
迴圈控制:
# break:跳出迴圈
print("找到第一個偶數:")
for num in range(1, 10):
if num % 2 == 0:
print(f"找到偶數:{num}")
break
print(f"{num} 是奇數")
# continue:跳過當前迭代
print("\n只印出奇數:")
for num in range(1, 10):
if num % 2 == 0:
continue # 跳過偶數
print(f"{num} 是奇數")
# 巢狀迴圈
print("\n九九乘法表:")
for i in range(1, 10):
for j in range(1, 10):
result = i * j
print(f"{i}×{j}={result:2d}", end=" ")
print() # 換行
# else 子句(迴圈正常結束時執行)
print("\n尋找質數:")
num = 17
for i in range(2, num):
if num % i == 0:
print(f"{num} 不是質數")
break
else:
print(f"{num} 是質數")
💡 實作練習
寫一個程式印出1到20之間所有的質數!
第7課:串列 (List)
進階學習如何使用串列來儲存和操作多個資料。
建立和存取串列:
# 建立串列
fruits = ["蘋果", "香蕉", "橘子"]
numbers = [1, 2, 3, 4, 5]
mixed = ["小明", 25, True, 175.5] # 可以混合不同型別
empty_list = [] # 空串列
print("水果串列:", fruits)
print("數字串列:", numbers)
print("混合串列:", mixed)
# 存取串列元素(索引從0開始)
print(f"第一個水果:{fruits[0]}")
print(f"第二個水果:{fruits[1]}")
print(f"最後一個水果:{fruits[-1]}") # 負索引從後面算
# 串列切片
print(f"前兩個水果:{fruits[0:2]}")
print(f"從第二個開始:{fruits[1:]}")
print(f"到第二個為止:{fruits[:2]}")
print(f"全部水果:{fruits[:]}")
# 串列長度
print(f"水果數量:{len(fruits)}")
# 檢查元素是否存在
if "蘋果" in fruits:
print("有蘋果!")
if "葡萄" not in fruits:
print("沒有葡萄")
串列操作:
# 修改串列
fruits = ["蘋果", "香蕉", "橘子"]
print("原始串列:", fruits)
# 修改元素
fruits[1] = "芒果"
print("修改後:", fruits)
# 新增元素
fruits.append("葡萄") # 在末尾新增
print("新增葡萄:", fruits)
fruits.insert(1, "草莓") # 在指定位置插入
print("插入草莓:", fruits)
# 刪除元素
fruits.remove("橘子") # 刪除指定元素
print("刪除橘子:", fruits)
deleted_fruit = fruits.pop() # 刪除並返回最後一個元素
print(f"刪除了:{deleted_fruit}")
print("刪除後:", fruits)
deleted_fruit = fruits.pop(0) # 刪除並返回指定位置的元素
print(f"刪除了:{deleted_fruit}")
print("刪除後:", fruits)
# 串列合併
more_fruits = ["鳳梨", "西瓜"]
fruits.extend(more_fruits) # 或使用 fruits += more_fruits
print("合併後:", fruits)
# 清空串列
# fruits.clear() # 清空所有元素
串列方法和實用技巧:
# 串列排序和搜尋
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print("原始數字:", numbers)
# 排序
numbers.sort() # 原地排序
print("排序後:", numbers)
numbers.sort(reverse=True) # 降序排序
print("降序排序:", numbers)
# 不改變原串列的排序
original = [3, 1, 4, 1, 5]
sorted_list = sorted(original)
print("原始:", original)
print("排序後:", sorted_list)
# 搜尋和計數
fruits = ["蘋果", "香蕉", "蘋果", "橘子", "蘋果"]
print(f"蘋果的位置:{fruits.index('蘋果')}") # 第一次出現的位置
print(f"蘋果出現次數:{fruits.count('蘋果')}")
# 反轉串列
fruits.reverse()
print("反轉後:", fruits)
# 串列推導式(List Comprehension)
squares = [x**2 for x in range(1, 6)]
print("平方數:", squares)
even_numbers = [x for x in range(1, 11) if x % 2 == 0]
print("偶數:", even_numbers)
# 多維串列
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print("矩陣:", matrix)
print(f"第二行第三列:{matrix[1][2]}") # 6
# 複製串列
original = [1, 2, 3]
copy1 = original.copy() # 淺複製
copy2 = original[:] # 切片複製
copy3 = list(original) # 轉換複製
print("原始:", original)
print("複製:", copy1)
💡 實作練習
建立一個學生成績串列,計算平均分數,找出最高分和最低分!
第8課:字典與集合
進階學習 Python 中的字典 (Dictionary) 和集合 (Set),掌握鍵值對資料結構。
字典 (Dictionary) 基礎:
# 建立字典
student = {
"name": "小明",
"age": 20,
"grade": "大二",
"subjects": ["數學", "物理", "程式設計"]
}
# 存取字典元素
print(f"姓名:{student['name']}")
print(f"年齡:{student['age']}")
# 使用 get() 方法(更安全)
print(f"科系:{student.get('major', '未設定')}")
# 新增或修改元素
student["major"] = "資訊工程"
student["age"] = 21
print("更新後的學生資料:")
print(student)
# 刪除元素
del student["grade"]
removed_subjects = student.pop("subjects")
print(f"移除的科目:{removed_subjects}")
# 檢查鍵是否存在
if "name" in student:
print(f"學生姓名:{student['name']}")
# 取得所有鍵、值、鍵值對
print("所有鍵:", list(student.keys()))
print("所有值:", list(student.values()))
print("所有鍵值對:", list(student.items()))
字典的進階操作:
# 巢狀字典
class_data = {
"class_name": "程式設計班",
"students": {
"001": {"name": "小明", "score": 85},
"002": {"name": "小華", "score": 92},
"003": {"name": "小美", "score": 78}
},
"teacher": {"name": "王老師", "subject": "程式設計"}
}
# 存取巢狀字典
print(f"班級:{class_data['class_name']}")
print(f"學生001的分數:{class_data['students']['001']['score']}")
# 遍歷字典
print("\n學生成績:")
for student_id, info in class_data["students"].items():
print(f"學號 {student_id}:{info['name']} - {info['score']}分")
# 字典推導式
scores = {student_id: info["score"]
for student_id, info in class_data["students"].items()}
print(f"\n成績字典:{scores}")
# 計算平均分數
average_score = sum(scores.values()) / len(scores)
print(f"平均分數:{average_score:.1f}")
# 合併字典
default_settings = {"theme": "light", "language": "zh-TW"}
user_settings = {"theme": "dark", "font_size": 14}
# Python 3.9+ 的合併語法
final_settings = default_settings | user_settings
print(f"最終設定:{final_settings}")
# 或使用 update() 方法
default_settings.update(user_settings)
print(f"更新後設定:{default_settings}")
集合 (Set) 基礎:
# 建立集合
fruits = {"蘋果", "香蕉", "橘子", "蘋果"} # 重複的元素會被自動移除
print(f"水果集合:{fruits}")
# 從串列建立集合(去除重複)
numbers = [1, 2, 2, 3, 3, 3, 4, 5]
unique_numbers = set(numbers)
print(f"唯一數字:{unique_numbers}")
# 空集合
empty_set = set() # 注意:{} 是空字典,不是空集合
# 新增元素
fruits.add("葡萄")
fruits.update(["草莓", "芒果"])
print(f"新增後:{fruits}")
# 移除元素
fruits.remove("香蕉") # 如果元素不存在會出錯
fruits.discard("鳳梨") # 如果元素不存在不會出錯
removed_fruit = fruits.pop() # 隨機移除一個元素
print(f"移除 {removed_fruit} 後:{fruits}")
# 檢查元素是否存在
if "蘋果" in fruits:
print("集合中有蘋果")
# 集合長度
print(f"水果種類數量:{len(fruits)}")
# 清空集合
fruits_copy = fruits.copy()
fruits.clear()
print(f"清空後:{fruits}")
print(f"備份:{fruits_copy}")
集合運算:
# 集合運算範例
math_students = {"小明", "小華", "小美", "小強", "小麗"}
english_students = {"小華", "小美", "小剛", "小芳", "小麗"}
print(f"數學班學生:{math_students}")
print(f"英文班學生:{english_students}")
# 聯集(Union)- 所有學生
all_students = math_students | english_students
# 或使用 math_students.union(english_students)
print(f"所有學生:{all_students}")
# 交集(Intersection)- 兩班都有的學生
both_classes = math_students & english_students
# 或使用 math_students.intersection(english_students)
print(f"兩班都有的學生:{both_classes}")
# 差集(Difference)- 只在數學班的學生
only_math = math_students - english_students
# 或使用 math_students.difference(english_students)
print(f"只在數學班的學生:{only_math}")
# 對稱差集(Symmetric Difference)- 只在一個班的學生
only_one_class = math_students ^ english_students
# 或使用 math_students.symmetric_difference(english_students)
print(f"只在一個班的學生:{only_one_class}")
# 子集合檢查
small_group = {"小明", "小華"}
print(f"{small_group} 是數學班的子集合:{small_group.issubset(math_students)}")
print(f"數學班是 {small_group} 的超集合:{math_students.issuperset(small_group)}")
# 檢查是否有交集
print(f"兩班有共同學生:{not math_students.isdisjoint(english_students)}")
實用範例 - 學生管理系統:
# 學生管理系統
class StudentManager:
def __init__(self):
self.students = {}
self.subjects = set()
def add_student(self, student_id, name, age):
"""新增學生"""
self.students[student_id] = {
"name": name,
"age": age,
"subjects": set(),
"scores": {}
}
print(f"學生 {name} 已新增")
def enroll_subject(self, student_id, subject):
"""學生選課"""
if student_id in self.students:
self.students[student_id]["subjects"].add(subject)
self.subjects.add(subject)
print(f"學生 {self.students[student_id]['name']} 已選修 {subject}")
else:
print("學生不存在")
def add_score(self, student_id, subject, score):
"""新增成績"""
if student_id in self.students:
if subject in self.students[student_id]["subjects"]:
self.students[student_id]["scores"][subject] = score
print(f"已記錄 {subject} 成績:{score}")
else:
print(f"學生未選修 {subject}")
else:
print("學生不存在")
def get_student_info(self, student_id):
"""取得學生資訊"""
if student_id in self.students:
student = self.students[student_id]
print(f"\n學生資訊:")
print(f"姓名:{student['name']}")
print(f"年齡:{student['age']}")
print(f"選修科目:{student['subjects']}")
print(f"成績:{student['scores']}")
if student['scores']:
avg_score = sum(student['scores'].values()) / len(student['scores'])
print(f"平均分數:{avg_score:.1f}")
else:
print("學生不存在")
def get_subject_students(self, subject):
"""取得選修某科目的學生"""
students_in_subject = set()
for student_id, info in self.students.items():
if subject in info["subjects"]:
students_in_subject.add(info["name"])
return students_in_subject
# 使用範例
manager = StudentManager()
# 新增學生
manager.add_student("001", "小明", 20)
manager.add_student("002", "小華", 19)
manager.add_student("003", "小美", 21)
# 學生選課
manager.enroll_subject("001", "數學")
manager.enroll_subject("001", "物理")
manager.enroll_subject("002", "數學")
manager.enroll_subject("002", "英文")
manager.enroll_subject("003", "物理")
manager.enroll_subject("003", "英文")
# 新增成績
manager.add_score("001", "數學", 85)
manager.add_score("001", "物理", 78)
manager.add_score("002", "數學", 92)
manager.add_score("002", "英文", 88)
# 查詢資訊
manager.get_student_info("001")
# 查詢選修數學的學生
math_students = manager.get_subject_students("數學")
print(f"\n選修數學的學生:{math_students}")
💡 實作練習
建立一個圖書館管理系統,使用字典儲存書籍資訊,使用集合管理借閱者和書籍類別!
第9課:函數定義與參數
進階學習如何定義自己的函數,使用參數和回傳值,讓程式碼更模組化和可重用。
函數基礎:
# 定義簡單函數
def greet():
"""問候函數"""
print("你好!歡迎學習 Python!")
# 呼叫函數
greet()
# 帶參數的函數
def greet_person(name):
"""問候特定人員的函數"""
print(f"你好,{name}!")
greet_person("小明")
greet_person("小華")
# 帶多個參數的函數
def introduce(name, age, city):
"""自我介紹函數"""
print(f"我是 {name},今年 {age} 歲,住在 {city}")
introduce("小美", 20, "台北")
# 帶預設值的參數
def greet_with_title(name, title="同學"):
"""帶預設稱謂的問候函數"""
print(f"你好,{title} {name}!")
greet_with_title("小明") # 使用預設值
greet_with_title("王老師", "老師") # 覆蓋預設值
# 關鍵字參數
def create_profile(name, age, city="未知", hobby="閱讀"):
"""建立個人檔案"""
print(f"姓名:{name}")
print(f"年齡:{age}")
print(f"城市:{city}")
print(f"興趣:{hobby}")
print("-" * 20)
# 不同的呼叫方式
create_profile("小明", 25)
create_profile("小華", 22, city="高雄")
create_profile("小美", 24, hobby="游泳", city="台中")
create_profile(age=23, name="小強") # 完全使用關鍵字參數
回傳值:
# 回傳單一值
def add_numbers(a, b):
"""加法函數"""
result = a + b
return result
sum_result = add_numbers(5, 3)
print(f"5 + 3 = {sum_result}")
# 回傳多個值
def calculate(a, b):
"""計算四則運算"""
addition = a + b
subtraction = a - b
multiplication = a * b
division = a / b if b != 0 else None
return addition, subtraction, multiplication, division
# 接收多個回傳值
add, sub, mul, div = calculate(10, 3)
print(f"10 + 3 = {add}")
print(f"10 - 3 = {sub}")
print(f"10 * 3 = {mul}")
print(f"10 / 3 = {div:.2f}")
# 回傳字典
def get_student_info(name, scores):
"""計算學生資訊"""
average = sum(scores) / len(scores)
grade = "A" if average >= 90 else "B" if average >= 80 else "C"
return {
"name": name,
"scores": scores,
"average": average,
"grade": grade
}
student = get_student_info("小明", [85, 92, 78, 96])
print(f"學生:{student['name']}")
print(f"平均分數:{student['average']:.1f}")
print(f"等級:{student['grade']}")
# 條件回傳
def check_age(age):
"""檢查年齡類別"""
if age < 18:
return "未成年"
elif age < 65:
return "成年人"
else:
return "長者"
print(f"15歲是:{check_age(15)}")
print(f"30歲是:{check_age(30)}")
print(f"70歲是:{check_age(70)}")
進階參數處理:
# *args - 可變位置參數
def sum_all(*numbers):
"""計算所有數字的總和"""
total = 0
for num in numbers:
total += num
return total
print(f"總和:{sum_all(1, 2, 3)}") # 6
print(f"總和:{sum_all(1, 2, 3, 4, 5)}") # 15
print(f"總和:{sum_all(10, 20)}") # 30
# **kwargs - 可變關鍵字參數
def create_user(**user_info):
"""建立使用者資料"""
print("使用者資料:")
for key, value in user_info.items():
print(f" {key}: {value}")
create_user(name="小明", age=25, city="台北")
create_user(name="小華", age=22, email="xiaohua@example.com", hobby="游泳")
# 混合使用
def process_data(required_param, *args, **kwargs):
"""處理資料的通用函數"""
print(f"必要參數:{required_param}")
print(f"額外位置參數:{args}")
print(f"關鍵字參數:{kwargs}")
process_data("重要資料", 1, 2, 3, name="測試", version=1.0)
# 解包參數
def multiply(a, b, c):
"""三個數相乘"""
return a * b * c
numbers = [2, 3, 4]
result = multiply(*numbers) # 解包串列
print(f"2 * 3 * 4 = {result}")
user_data = {"name": "小明", "age": 25, "city": "台北"}
create_user(**user_data) # 解包字典
# Lambda 函數(匿名函數)
square = lambda x: x ** 2
print(f"5的平方:{square(5)}")
# 在其他函數中使用 lambda
numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(lambda x: x ** 2, numbers))
print(f"平方數:{squared_numbers}")
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(f"偶數:{even_numbers}")
實用函數範例:
# 計算機函數庫
def calculator():
"""簡單計算機"""
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
if b == 0:
return "錯誤:除數不能為零"
return a / b
def power(a, b):
return a ** b
def factorial(n):
"""計算階乘"""
if n < 0:
return "錯誤:負數沒有階乘"
if n == 0 or n == 1:
return 1
result = 1
for i in range(2, n + 1):
result *= i
return result
# 回傳函數字典
return {
"add": add,
"subtract": subtract,
"multiply": multiply,
"divide": divide,
"power": power,
"factorial": factorial
}
# 使用計算機
calc = calculator()
print(f"5 + 3 = {calc['add'](5, 3)}")
print(f"10 - 4 = {calc['subtract'](10, 4)}")
print(f"6 * 7 = {calc['multiply'](6, 7)}")
print(f"15 / 3 = {calc['divide'](15, 3)}")
print(f"2^8 = {calc['power'](2, 8)}")
print(f"5! = {calc['factorial'](5)}")
# 文字處理函數
def text_analyzer(text):
"""分析文字的函數"""
def word_count():
return len(text.split())
def char_count():
return len(text)
def char_count_no_spaces():
return len(text.replace(" ", ""))
def most_common_char():
char_freq = {}
for char in text.lower():
if char.isalpha():
char_freq[char] = char_freq.get(char, 0) + 1
if char_freq:
return max(char_freq, key=char_freq.get)
return None
return {
"text": text,
"word_count": word_count(),
"char_count": char_count(),
"char_count_no_spaces": char_count_no_spaces(),
"most_common_char": most_common_char()
}
# 分析文字
sample_text = "Python 是一種很棒的程式語言"
analysis = text_analyzer(sample_text)
print(f"文字:{analysis['text']}")
print(f"字數:{analysis['word_count']}")
print(f"字元數:{analysis['char_count']}")
print(f"字元數(不含空格):{analysis['char_count_no_spaces']}")
print(f"最常出現的字元:{analysis['most_common_char']}")
# 遞迴函數範例
def fibonacci(n):
"""計算費波那契數列"""
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print("費波那契數列前10項:")
for i in range(10):
print(f"F({i}) = {fibonacci(i)}")
# 改良版(使用記憶化)
def fibonacci_memo(n, memo={}):
"""使用記憶化的費波那契函數"""
if n in memo:
return memo[n]
if n <= 1:
return n
memo[n] = fibonacci_memo(n-1, memo) + fibonacci_memo(n-2, memo)
return memo[n]
print(f"F(30) = {fibonacci_memo(30)}") # 更快的計算
💡 實作練習
建立一個密碼生成器函數,可以根據指定長度和複雜度要求生成安全密碼!
第10課:檔案處理與異常處理
進階學習如何讀寫檔案,以及如何處理程式執行時可能發生的錯誤。
檔案讀取:
# 基本檔案讀取
# 方法1:手動關閉檔案
file = open("example.txt", "r", encoding="utf-8")
content = file.read()
print(content)
file.close()
# 方法2:使用 with 語句(推薦)
with open("example.txt", "r", encoding="utf-8") as file:
content = file.read()
print(content)
# 檔案會自動關閉
# 讀取檔案的不同方式
with open("example.txt", "r", encoding="utf-8") as file:
# 讀取整個檔案
all_content = file.read()
print("整個檔案:")
print(all_content)
with open("example.txt", "r", encoding="utf-8") as file:
# 逐行讀取
print("\n逐行讀取:")
for line_number, line in enumerate(file, 1):
print(f"第{line_number}行:{line.strip()}")
with open("example.txt", "r", encoding="utf-8") as file:
# 讀取所有行到串列
lines = file.readlines()
print(f"\n總共 {len(lines)} 行")
for i, line in enumerate(lines):
print(f"行 {i+1}: {line.strip()}")
# 讀取指定行數
with open("example.txt", "r", encoding="utf-8") as file:
first_line = file.readline().strip()
second_line = file.readline().strip()
print(f"第一行:{first_line}")
print(f"第二行:{second_line}")
# 檢查檔案是否存在
import os
filename = "example.txt"
if os.path.exists(filename):
print(f"檔案 {filename} 存在")
with open(filename, "r", encoding="utf-8") as file:
content = file.read()
print(f"檔案大小:{len(content)} 字元")
else:
print(f"檔案 {filename} 不存在")
檔案寫入:
# 寫入檔案(覆蓋模式)
with open("output.txt", "w", encoding="utf-8") as file:
file.write("這是第一行\n")
file.write("這是第二行\n")
file.write("這是第三行\n")
print("檔案寫入完成")
# 附加模式(不覆蓋原內容)
with open("output.txt", "a", encoding="utf-8") as file:
file.write("這是附加的第四行\n")
file.write("這是附加的第五行\n")
# 寫入串列內容
lines_to_write = [
"Python 是很棒的語言\n",
"檔案處理很重要\n",
"記得要處理異常\n"
]
with open("lines_output.txt", "w", encoding="utf-8") as file:
file.writelines(lines_to_write)
# 格式化寫入
students = [
{"name": "小明", "age": 20, "score": 85},
{"name": "小華", "age": 19, "score": 92},
{"name": "小美", "age": 21, "score": 78}
]
with open("students.txt", "w", encoding="utf-8") as file:
file.write("學生成績報告\n")
file.write("=" * 30 + "\n")
for student in students:
line = f"姓名:{student['name']:<6} 年齡:{student['age']:<3} 分數:{student['score']}\n"
file.write(line)
average = sum(s['score'] for s in students) / len(students)
file.write(f"\n平均分數:{average:.1f}\n")
print("學生資料已寫入檔案")
# 同時讀寫檔案
with open("data.txt", "w+", encoding="utf-8") as file:
# 先寫入
file.write("第一行資料\n第二行資料\n第三行資料\n")
# 移動到檔案開頭
file.seek(0)
# 讀取內容
content = file.read()
print("檔案內容:")
print(content)
異常處理基礎:
# 基本 try-except 結構
try:
number = int(input("請輸入一個數字:"))
result = 10 / number
print(f"10 除以 {number} 等於 {result}")
except ValueError:
print("錯誤:請輸入有效的數字")
except ZeroDivisionError:
print("錯誤:不能除以零")
# 捕捉多種異常
def safe_divide(a, b):
try:
result = a / b
return result
except ZeroDivisionError:
print("錯誤:除數不能為零")
return None
except TypeError:
print("錯誤:參數必須是數字")
return None
print(safe_divide(10, 2)) # 正常情況
print(safe_divide(10, 0)) # 除零錯誤
print(safe_divide(10, "a")) # 型別錯誤
# 使用 else 和 finally
def read_file_safe(filename):
try:
with open(filename, "r", encoding="utf-8") as file:
content = file.read()
except FileNotFoundError:
print(f"錯誤:找不到檔案 {filename}")
content = None
except PermissionError:
print(f"錯誤:沒有權限讀取檔案 {filename}")
content = None
else:
print(f"成功讀取檔案 {filename}")
finally:
print("檔案讀取操作完成")
return content
# 測試
content = read_file_safe("existing_file.txt")
content = read_file_safe("non_existing_file.txt")
# 捕捉所有異常
def risky_operation(data):
try:
# 可能出錯的操作
result = data[0] / data[1]
return result
except Exception as e:
print(f"發生未預期的錯誤:{type(e).__name__}: {e}")
return None
print(risky_operation([10, 2])) # 正常
print(risky_operation([10, 0])) # 除零錯誤
print(risky_operation([])) # 索引錯誤
進階異常處理:
# 自定義異常
class InvalidAgeError(Exception):
"""年齡無效的自定義異常"""
def __init__(self, age, message="年齡必須在 0 到 150 之間"):
self.age = age
self.message = message
super().__init__(self.message)
class InvalidScoreError(Exception):
"""分數無效的自定義異常"""
pass
def validate_age(age):
"""驗證年齡"""
if not isinstance(age, int):
raise TypeError("年齡必須是整數")
if age < 0 or age > 150:
raise InvalidAgeError(age)
return True
def validate_score(score):
"""驗證分數"""
if not isinstance(score, (int, float)):
raise TypeError("分數必須是數字")
if score < 0 or score > 100:
raise InvalidScoreError(f"分數 {score} 超出範圍 (0-100)")
return True
# 使用自定義異常
def create_student(name, age, score):
try:
validate_age(age)
validate_score(score)
return {
"name": name,
"age": age,
"score": score,
"status": "valid"
}
except (InvalidAgeError, InvalidScoreError, TypeError) as e:
print(f"建立學生資料失敗:{e}")
return {"status": "error", "message": str(e)}
# 測試
print(create_student("小明", 20, 85)) # 正常
print(create_student("小華", -5, 90)) # 年齡錯誤
print(create_student("小美", 25, 150)) # 分數錯誤
# 重新拋出異常
def process_data(data):
try:
# 處理資料
result = complex_calculation(data)
return result
except ValueError as e:
print(f"資料處理警告:{e}")
# 重新拋出異常讓上層處理
raise
except Exception as e:
print(f"未知錯誤:{e}")
# 轉換為更具體的異常
raise RuntimeError(f"資料處理失敗:{e}") from e
def complex_calculation(data):
if not data:
raise ValueError("資料不能為空")
return sum(data) / len(data)
# 異常鏈
try:
result = process_data([])
except RuntimeError as e:
print(f"最終錯誤:{e}")
print(f"原始錯誤:{e.__cause__}")
# 使用 assert 進行除錯
def calculate_average(scores):
assert isinstance(scores, list), "分數必須是串列"
assert len(scores) > 0, "分數串列不能為空"
assert all(isinstance(score, (int, float)) for score in scores), "所有分數必須是數字"
return sum(scores) / len(scores)
# 在除錯模式下會檢查 assert
try:
avg = calculate_average([85, 92, 78])
print(f"平均分數:{avg}")
# 這會觸發 AssertionError
avg = calculate_average([])
except AssertionError as e:
print(f"斷言錯誤:{e}")
實用範例 - 日誌系統:
import datetime
import os
class Logger:
"""簡單的日誌系統"""
def __init__(self, log_file="app.log"):
self.log_file = log_file
self.ensure_log_directory()
def ensure_log_directory(self):
"""確保日誌目錄存在"""
log_dir = os.path.dirname(self.log_file)
if log_dir and not os.path.exists(log_dir):
try:
os.makedirs(log_dir)
except OSError as e:
print(f"無法建立日誌目錄:{e}")
def write_log(self, level, message):
"""寫入日誌"""
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {level}: {message}\n"
try:
with open(self.log_file, "a", encoding="utf-8") as file:
file.write(log_entry)
except Exception as e:
print(f"寫入日誌失敗:{e}")
def info(self, message):
"""資訊日誌"""
self.write_log("INFO", message)
print(f"INFO: {message}")
def warning(self, message):
"""警告日誌"""
self.write_log("WARNING", message)
print(f"WARNING: {message}")
def error(self, message):
"""錯誤日誌"""
self.write_log("ERROR", message)
print(f"ERROR: {message}")
def read_logs(self, lines=10):
"""讀取最近的日誌"""
try:
with open(self.log_file, "r", encoding="utf-8") as file:
all_lines = file.readlines()
recent_lines = all_lines[-lines:] if len(all_lines) > lines else all_lines
return recent_lines
except FileNotFoundError:
return ["日誌檔案不存在"]
except Exception as e:
return [f"讀取日誌失敗:{e}"]
# 檔案處理工具類
class FileManager:
"""檔案管理工具"""
def __init__(self):
self.logger = Logger("logs/file_manager.log")
def safe_read_file(self, filename):
"""安全讀取檔案"""
try:
self.logger.info(f"開始讀取檔案:{filename}")
with open(filename, "r", encoding="utf-8") as file:
content = file.read()
self.logger.info(f"成功讀取檔案:{filename},大小:{len(content)} 字元")
return content
except FileNotFoundError:
error_msg = f"檔案不存在:{filename}"
self.logger.error(error_msg)
return None
except PermissionError:
error_msg = f"沒有權限讀取檔案:{filename}"
self.logger.error(error_msg)
return None
except UnicodeDecodeError:
error_msg = f"檔案編碼錯誤:{filename}"
self.logger.error(error_msg)
return None
except Exception as e:
error_msg = f"讀取檔案時發生未知錯誤:{filename} - {e}"
self.logger.error(error_msg)
return None
def safe_write_file(self, filename, content):
"""安全寫入檔案"""
try:
self.logger.info(f"開始寫入檔案:{filename}")
# 確保目錄存在
directory = os.path.dirname(filename)
if directory and not os.path.exists(directory):
os.makedirs(directory)
with open(filename, "w", encoding="utf-8") as file:
file.write(content)
self.logger.info(f"成功寫入檔案:{filename},大小:{len(content)} 字元")
return True
except PermissionError:
error_msg = f"沒有權限寫入檔案:{filename}"
self.logger.error(error_msg)
return False
except OSError as e:
error_msg = f"寫入檔案時發生系統錯誤:{filename} - {e}"
self.logger.error(error_msg)
return False
except Exception as e:
error_msg = f"寫入檔案時發生未知錯誤:{filename} - {e}"
self.logger.error(error_msg)
return False
# 使用範例
file_manager = FileManager()
# 測試讀取檔案
content = file_manager.safe_read_file("test.txt")
if content:
print("檔案內容:", content[:100]) # 只顯示前100字元
# 測試寫入檔案
test_content = "這是測試內容\n包含多行文字\n用於測試檔案寫入功能"
success = file_manager.safe_write_file("output/test_output.txt", test_content)
if success:
print("檔案寫入成功")
else:
print("檔案寫入失敗")
# 查看日誌
logger = Logger("logs/file_manager.log")
recent_logs = logger.read_logs(5)
print("\n最近的日誌:")
for log in recent_logs:
print(log.strip())
💡 實作練習
建立一個配置檔案管理器,能夠讀取和寫入 JSON 格式的設定檔,並包含完整的錯誤處理!