🚀 成為工程師的進步備忘錄
📖 前言與導讀
關於作者與現況
我並非程式小白。作為一名自學開發者,過去我已具備全端開發與部署的實戰經驗:
- 🖥️ 後端與維運:使用 Django (REST API)、Ubuntu 部署、Nginx 反向代理、Docker 容器化與 CI/CD 流程。
- 📱 應用開發:使用 Kotlin 開發 Android App、Qt6 (PyQt) 桌面應用、以及 Line Bot 整合。
- 🤖 AI 實作:使用 YOLOv8 + OpenCV 完成影像辨識與串接。
🛑 然而,我意識到了技術債:
「我能看懂邏輯,也能拼湊出功能,但在『基礎演算法、SQL 優化、資料結構、手刻底層』方面,地基不夠扎實。」
這份筆記不是從零教學,而是我 「從能開發 (Make it work) → 能架構 (Make it right)」 的進步藍圖。
🎯 核心目標
「我不只是想讓程式能跑,而是想理解它為什麼能這樣跑。」
這份筆記將專注於解決三大痛點:
1. 補回手寫能力:不再依賴自動補全,強化 Python、SQL、演算法的手刻實力。
2. 強化架構理解:深入理解後端框架原理、非同步處理與部署細節。
3. 建立技術深度:從單純呼叫 AI API,轉變為能自主設計解法。
✍️ 結語
這是一份屬於「實作派」工程師的筆記。
紀錄從「讓專案跑起來」開始,直到每個架構、每段邏輯都真正「被我理解」為止。
🗺️ 學習路徑導覽
這是我的後端工程師修煉地圖,從核心語言到底層邏輯,再到架構設計。
| 標題 | 核心內容 |
|---|---|
| Python 筆記 | 基礎語法、記憶體、進階黑魔法 |
| 資料結構與演算法 | LeetCode 刷題、複雜度分析 |
| 資料庫與 SQL 實戰 | SQL 手寫、索引優化 (Index)、ORM vs SQL 對照 |
| Web 後端框架 | Django / FastAPI / Flask (框架比較與實作) |
| Linux 與開發工具箱 | Vim, Nano, Git, Shell, Ubuntu 指令 (開發環境) |
| 基礎設施與部署維運 | Docker, Nginx, Network, CI/CD (生產環境) |
| 前端與客戶端開發 | JS/React, Kotlin/Android, Qt (跨域擴充) |
🐍 Python 筆記
💡 語言概論與定位
⚙️ 運行機制:解釋型(直譯型) vs. 編譯型
這是關於程式碼執行的效率與時機的權衡。
| 特性 | 編譯型 (Compiled) | 直譯/解釋型 (Interpreted) |
|---|---|---|
| 翻譯時機 | 運行前 一次性 | 運行時 逐行 |
| 執行速度 | 🚀 快 (直接與 CPU 溝通) | 🐢 慢 (翻譯需耗時) |
| 開發權衡 | 開發慢,運行快 | 開發快,運行慢 |
🔎 Python 的特殊性:混合型與 PVM
- 機制: Python 屬於混合型/直譯型。原始碼會先被編譯成 位元碼 (.pyc),再由 PVM (Python 虛擬機) 這個核心直譯器逐行執行。
- PVM (Python Virtual Machine): 它是 Python 的核心直譯器。這讓 Python 程式碼具有跨平台的能力。
🛡️ 型別系統總覽:四象限比較 (安全與靈活的取捨)
型別系統的選擇,是「程式碼安全性」與「開發速度/靈活性」之間的權衡。
① 型別強度:強型別 vs. 弱型別 (安全性對比)
| 特性 | 強型別 (Strongly Typed) | 弱型別 (Weakly Typed) |
|---|---|---|
| 判斷依據 | ❌ 不允許 隱式轉換,必須手動轉換。 | ✅ 允許 隱式轉換,語言會嘗試自動處理。 |
| 優勢 | 程式碼 安全性高,避免意外的數據操作。 | 寫作方便,適合快速腳本。 |
| 代表語言 | Python, Kotlin, Java | JavaScript, PHP |
② 檢查時機:靜態型別 vs. 動態型別 (靈活性對比)
| 特性 | 靜態型別 (Statically Typed) | 動態型別 (Dynamically Typed) |
|---|---|---|
| 判斷依據 | 編譯時 確定型別,運行前固定 (如 Kotlin)。 | 運行時 才檢查型別,可以隨時改變 (如 Python)。 |
| 優勢 | 程式碼 效率高,編譯時就能排除大量錯誤。 | 極致靈活性,開發速度快,不需要事前宣告型別。 |
| 代表語言 | Kotlin, Java, Go | Python, JavaScript, Ruby |
🎯 結論:Python 的定位
Python 採用 動態型別 (靈活) + 強型別 (安全) 的組合。
- 代價: 缺乏靜態型別帶來的絕對運行速度優勢 (需要 PVM 額外直譯)。
- 收穫: 享受動態型別的快速原型開發優勢,同時藉由強型別避免常見的隱式轉換 Bug。
🚀 Python 的優勢與工程定位 (Why the Choice?)
| 優勢特性 | 說明 | 工程定位 (Why we use it) |
|---|---|---|
| 生態系統廣 | 龐大且成熟的第三方庫 (AI/Web/Data Science)。 | 數據科學、機器學習 (AI)、Web 後端服務 |
| 高可讀性 | 語法接近自然語言,維護性高。 | 長期維護專案、團隊協作 |
| 膠水語言 | 擅長快速串接不同技術組件。 | 自動化腳本、維運工具 |
語言基礎與手刻能力
🧠 Python 世界觀:變數與記憶體機制
核心概念: 變數 (Variable) 是指向記憶體中 物件 (Object) 的「標籤 (Label) 或引用 (Reference)」,而非儲存值的容器 (Box)。
變數的本質:標籤與引用
- 賦值過程:
x = 10的行為是:先創建值為10的物件,再將x標籤貼上去。 - 多標籤: 執行
y = x時,y標籤會指向x所指向的同一個物件。 - 記憶體回收: 當物件沒有任何標籤指向它時(引用計數為零),會被 垃圾回收機制 (GC) 釋放記憶體。
🔗 追蹤物件身份:id() 與 is 運算符
id(obj): 回傳物件在記憶體中的唯一識別碼。用來判斷物件本身是否相同。is運算符: 判斷兩個變數是否指向同一個物件 (即id()是否相等)。- 對比:
is判斷身份,==判斷值是否相等。
💻 驗證程式碼:
a = [1, 2]
b = [1, 2] # 創建了兩個不同的 List 物件
print(a is b) # False (身份不同)
print(a == b) # True (值相等)
🔄 可變與不可變物件的記憶體行為 (核心)
| 特性 | 不可變物件 (Immutable) | 可變物件 (Mutable) |
|---|---|---|
| 代表型別 | int, str, tuple | float,list, dict, set |
| 修改行為 | 創建一個新的物件,並讓變數指向新物件。舊物件等待 GC 處理。 | 在原地修改 物件的內容 |
| 結果 | id() 改變 | id() 維持不變 |
💻 實戰範例 (ID 追蹤):
# --- Immutable 範例:int ---
i = 100
print(f"原始 ID: {id(i)}")
i += 1 # 發生修改時,i 轉而指向 ID 不同的新物件
print(f"修改後 ID: {id(i)}") # ID 改變!
# --- Mutable 範例:list ---
L = [1, 2]
print(f"原始 ID: {id(L)}")
L.append(3) # 在原地修改內容,不創建新物件
print(f"修改後 ID: {id(L)}") # ID 相同!
⚠️ 記憶體優化:小整數與字串快取 (Interning)
-
陷阱: Python 會對特定範圍的小整數 (通常是 [-5, 256]) 和某些短字串進行快取,這是為了提升效能。
-
結果: 在快取範圍內,相同值的變數會指向同一個物件,導致 is 判斷為 True。
💻 範例:
a = 256
b = 256
print(a is b) # True (優化快取)
a = 257
b = 257
print(a is b) # False (一般情況)
資料型態總覽與比較
核心概念: 透過理解每個容器的特性(可變性、有序性、可索引性),來選擇最適合特定場景的數據結構。
核心型態分類與對比
| 型態分類 | 範例 | 可變性 (Mutable?) | 有序性 (Ordered?) | 可索引 (Indexable?) |
|---|---|---|---|---|
| 數值型別 | int, float, bool |
❌ 否 | N/A | ❌ 否 |
| 不可變序列 | str (字串), tuple |
❌ 否 | ✅ 是 | ✅ 是 |
| 可變序列 | list (列表) |
✅ 是 | ✅ 是 | ✅ 是 |
| 無序容器 | set (集合) |
✅ 是 | ❌ 否 | ❌ 否 |
| 對應容器 | dict (字典) |
✅ 是 | ✅ 是 (Python 3.7+ 保證有序) | ❌ 否 (透過 Key 存取) |
🔢 數值與布林型別 (int, float, bool)
核心: 數值型別的記憶體行為是 不可變 (Immutable) 的。了解
float的精度陷阱,是避免潛在 Bug 的關鍵。
① 整數 (int) 運算與位元操作
Python 的整數大小只受限於系統記憶體。
- 常用數學運算:
+,-,*,/(結果為float)//(整數除法,向下取整)**(冪次運算)%(取餘數)
- 位元運算 (Bitwise Operations): 這是用於底層計算或優化的工具。
&(AND),|(OR),^(XOR)~(NOT)<<(左移),>>(右移):用於快速乘除 2 的冪次。
② 浮點數 (float) 與精度陷阱
- IEEE 754 標準: Python 的
float遵循此標準,但這標準會導致無法精確表達某些小數(如 0.1)。 - 陷阱範例:
print(0.1 + 0.2 == 0.3) #結果為 False,而非 True,這是 float 精度問題
- 解決方案: 當處理金融、稅務或需要高精度的計算時,應使用標準庫中的 decimal 模組。
③ 布林 (bool) 與真值性 (Truthiness)
-
核心邏輯運算符:
-
and (且), or (或), not (非)。
-
短路求值 (Short-circuiting): 在 a and b 中,若 a 為 False,則不會計算 b;在 a or b 中,若 a 為 True,則不會計算 b。這在性能和防止錯誤上很重要。
-
真值性 (Truthiness): Python 的一個獨特概念,任何物件在布林語境下都有一個布林值。
-
False 的值: False, None, 數字 0, 空字串 “”, 空列表 [], 空字典 {} 等。
-
True 的值: 任何非 False 的物件或非零數字。
🏷️ 序列型別:字串 (str) 與位元組 (bytes)
核心: 字串 (
str) 是不可變的文本序列;位元組 (bytes) 是不可變的二進制序列。理解 編碼 (Encoding),是處理文件和網路數據的關鍵。
① 字串 (str) 的不可變性與方法
- 不可變性再強調: 字串是 Immutable。對字串的任何修改(如替換、連接)都會在記憶體中生成一個新的字串物件。
- 高效格式化:
f-string(格式化字串文字): 最簡潔、高效的格式化方式 (f"我的分數是 {score}")。.format():傳統但仍常用的格式化方法。
- 常用方法實戰:
- 切片 (Slicing):
s[start:stop:step]的靈活運用。- 關鍵技巧: 負索引 (Negative Index) 可從後方開始計數。
- 💻 範例: 倒轉字串:
my_str[::-1]
- 常用方法:
- 檢查:
.startswith(),.endswith(),.isdigit()(快速判斷字串內容)。 - 替換/清除:
.replace(),.strip()(去除頭尾空白或指定字元)。
- 檢查:
② 編碼關鍵:str vs. bytes
str(文本): 用於儲存人類可讀的文本,如名字、文章。bytes(二進制): 用於儲存機器可讀的數據,如圖片、音樂、網路傳輸的數據。- 轉換橋樑:
- 編碼 (
.encode()): 將str轉換為bytes(例如:"中文".encode('utf-8'))。 - 解碼 (
.decode()): 將bytes轉換為str(例如:b'\xe4\xb8\xad'.decode('utf-8'))。
- 編碼 (
- 標準編碼: UTF-8 是目前網頁、系統、Python 中最廣泛使用的編碼標準,因為它能兼容多數語言。
💻 實戰範例 (編碼解碼):
text = "你好"
1. 編碼:從 str 變成 bytes,機器才能傳輸或儲存
encoded_bytes = text.encode('utf-8')
print(f"編碼結果: {encoded_bytes}")
2. 解碼:從 bytes 變回 str,人才能閱讀
decoded_text = encoded_bytes.decode('utf-8')
print(f"解碼結果: {decoded_text}")
容器型別:List (列表) 深入解析 (可變序列)
核心: List 是 Python 最常用的容器,特性是 可變 (Mutable)、有序 (Ordered)、可索引 (Indexable)。理解其操作的 時間複雜度 是高效程式設計的基礎。
① 列表的記憶體特性與可變性
- 對比: 與字串 (
str) 不同,列表支援原地修改(In-place Modification),修改內容時id()不變。 - 常見操作:
.append(),.pop(),.sort(),L[index] = new_value。
② 關鍵操作的性能分析 (時間複雜度)
在高效能設計中,應盡量選擇 $O(1)$ 的操作。
| 操作方法 | 時間複雜度 (T) | 說明 |
|---|---|---|
| 末尾新增/移除 | $O(1)$ | .append(), .pop() (通常是常數時間) |
| 索引存取 | $O(1)$ | L[i] (直接根據地址計算位置) |
| 開頭或中間插入/刪除 | $O(n)$ | .insert(0, x), del L[0] (需要移動所有後續元素) |
| 查找 | $O(n)$ | x in L, .index() (需要遍歷整個列表) |
③ 高效寫法:列表生成式 (List Comprehension)
- 定義: 一種簡潔、高效地創建列表的語法。
- 優勢: 速度通常比傳統的
for迴圈搭配.append()快,因為 Python 可以進行底層優化。
💻 範例:
# 傳統寫法 (較慢)
squares = []
for i in range(10):
squares.append(i * i)
# 列表生成式 (高效、簡潔)
squares_comp = [i * i for i in range(10)]
④ 記憶體陷阱:淺複製 (Shallow Copy) 與深複製 (Deep Copy)
-
陷阱原因: 由於列表是 Mutable 的,直接賦值 (L2 = L1) 只是複製了標籤。
-
淺複製 (Shallow Copy):
-
方法: L2 = L1.copy() 或 L2 = L1[:]。
-
效果: 複製了第一層的元素。但如果列表內包含其他可變容器(如 List of Lists),內層容器仍是共享引用。
-
-
深複製 (Deep Copy):
-
方法: 需使用 copy 模組的 copy.deepcopy(L1)。
-
效果: 遞歸複製所有嵌套的物件,確保兩者在記憶體中完全獨立。
-
容器型別:Tuple (元組) 深入解析 (不可變序列)
核心: Tuple 與 List 一樣是 有序 (Ordered)、可索引 (Indexable) 的序列,但 Tuple 是 不可變 (Immutable) 的。
① 不可變性帶來的工程優勢
- 數據保護: 一旦創建就不能修改,確保數據在程式運行中保持完整性 (Data Integrity)。
- 作爲字典的 Key: 由於 Tuple 是不可變的,它可以作為字典 (
dict) 的鍵 (Key)。List 因為是可變的,則不能作為 Key。 - 性能/記憶體: 相較於 List,Tuple 在內部結構上更精簡,在存取和疊代時有輕微的性能和記憶體優勢。
② 語法與應用:元組解包 (Tuple Unpacking)
- 定義: 將元組的元素,一次性賦值給多個變數。這是 Python 非常常見且強大的寫法。
- 應用場景:
- 函式返回值: 函式返回多個值時,本質上是返回一個 Tuple。
- 變數交換: 無需中間變數即可交換兩個變數的值 (
a, b = b, a)。
💻 範例 (元組解包):
# 函式返回多個值
def get_user_info():
return "Alice", 30 # 本質上返回一個 ('Alice', 30) 的 Tuple
name, age = get_user_info() # 解包
③ ⚠️ 不可變性的陷阱:內部可變元素
-
陷阱: Tuple 的不可變性僅保護了 Tuple 自身的第一層結構(即:它內部的標籤不能被替換或重新指派)。
-
結論: 如果 Tuple 內部包含一個 可變物件 (如 List),則該內部物件是可以被修改內容的。
| 語法 | 動作本質 | 是否改變 Tuple 結構 | 結果 |
|---|---|---|---|
| “T[0] = [9, 9]” | 嘗試 替換 內部標籤的指向 | 是,違反 Immutability | 💥 錯誤 |
| T[0].append(4) | 修改 標籤指向的 List 內容 | 否,Tuple 結構未動 | ✅ 正確 |
💻 範阱範例:
T = ([1, 2], 3)
# T[0] = [9, 9] # 💥 錯誤!企圖替換 Tuple 索引 0 的標籤
T[0].append(4) # ✅ 正確!修改了 List 物件 [1, 2] 的內容
print(T) # 輸出: ([1, 2, 4], 3)
Dict (字典) 深入解析 (映射容器)
核心: Dict 是一種 可變 (Mutable) 的 鍵值對 (Key-Value Pair) 容器,其查找速度極快,接近 $O(1)$ (常數時間)。
① Dict 的性能基礎:雜湊 (Hashing) 原理
- 底層結構: 字典是基於 雜湊表 (Hash Table) 實現的。
- 雜湊函式: 每個鍵 (Key) 會透過一個雜湊函式,被轉換成一個唯一的整數(雜湊值),這個雜湊值決定了數據在記憶體中的儲存位置。
- $O(1)$ 的原因: 查找數據時,Python 直接計算 Key 的雜湊值,然後跳轉到對應的儲存位置,省去了遍歷的時間。
② 核心規則:鍵 (Key) 必須是不可變物件 (Immutable)
- 為什麼? 因為 Key 的雜湊值必須在它的生命週期內保持不變。
- 結果: 只有 不可變物件 (
int,str,tuple,float) 可以作為字典的 Key。 - 陷阱:
list和set因為是可變的,不能作為 Key。
③ 實用操作與高效存取
- 安全存取:
dict.get(key, default): 推薦使用!當 Key 不存在時,會回傳你設定的default值 (或None),而不是拋出KeyError,使程式更健壯。dict[key]: 當 Key 不存在時,會拋出KeyError。
- 新增/更新: 使用
dict[new_key] = new_value。 - 刪除: 使用
del dict[key]或.pop(key)。 - 視圖物件 (View Objects):
.keys(),.values(),.items()回傳的是動態視圖,它們會反映字典的實時變化。
④ 字典的有序性 (Python 3.7+)
- 歷史: 在 Python 3.7 之後,字典在語言規格上保證了插入順序。
- 結論: 現在的字典既高效,又保留了插入的順序。
容器型別:Set (集合) 深入解析 (無序容器)
核心: Set 是 可變 (Mutable)、無序 (Unordered) 的容器,且其所有元素都必須是 唯一 的 (不重複)。
① 性能原理與唯一性
- 底層結構: 與 Dict 類似,Set 也是基於 雜湊表 (Hash Table) 實現的,但它只儲存鍵 (Key),不儲存值 (Value)。
- 高效檢查: 由於雜湊表的特性,檢查元素是否存在於集合中 (
element in my_set) 的速度極快,約為 $O(1)$。 - 元素限制: Set 中的元素必須是 不可變物件 (Immutable)。原因與 Dict 的 Key 相同:需要固定的雜湊值來確定儲存位置。
② 核心應用:去重與高效查找
- 快速去重: 將 List 轉換為 Set 是最快的去重方式。
- 範例:
unique_list = list(set(my_list))
- 範例:
- 高效查找: 當你需要頻繁檢查一個元素是否在一個大型數據集中時,Set 的性能遠優於 List。
③ 集合運算 (Set Operations)
Set 支援標準的數學集合運算方法,這在數據分析和邏輯判斷中非常實用。
| 運算符 | 方法 | 數學意義 | 說明 |
|---|---|---|---|
| |
.union() |
聯集 (Union) | 包含所有集合的元素。 |
& |
.intersection() |
交集 (Intersection) | 包含所有集合共有的元素。 |
- |
.difference() |
差集 (Difference) | 包含在第一個集合中,但不在第二個集合中的元素。 |
^ |
.symmetric_difference() |
對稱差集 | 包含在任意一個集合中,但不包含在兩者交集中的元素。 |
核心數據型態方法總整理 (Methods)
核心: 方法 (Method) 是綁定在特定數據型別上的函式,它們用於對該物件進行操作。
List (列表) 常用方法 (Mutable)
| 方法 | 用途/說明 | 參數 | 範例 |
|---|---|---|---|
.append() |
末尾新增 | x (單一元素) |
L.append(5) |
.pop() |
末尾/索引移除 | [index] (可選,預設移除末尾) |
L.pop() / L.pop(0) |
.insert() |
中間插入 | (index, x) |
L.insert(0, 'start') |
.remove() |
按值移除 | x (移除第一個匹配的值) |
L.remove('apple') |
.sort() |
原地排序 | (key=func, reverse=bool) |
L.sort(reverse=True) |
.copy() |
淺複製 | 無 | L2 = L.copy() |
| 切片 (Slicing) | 提取/倒轉 | [start:stop:step] |
L[::-1] (倒轉) |
String (字串) 常用方法 (Immutable)
| 方法 | 用途/說明 | 參數 | 範例 |
|---|---|---|---|
.split() |
分割字串 | [sep] (分隔符,預設空白) |
s.split(',') |
.join() |
組合字串 | iterable (可疊代物件) |
",".join(my_list) |
.strip() |
去除空白 | [chars] (要去除的字元,預設空白) |
s.strip() |
.replace() |
替換內容 | (old, new, [count]) |
s.replace('a', 'b') |
.startswith() |
開頭檢查 | prefix (前綴) |
s.startswith('http') |
.encode() |
編碼 | [encoding] (預設 ‘utf-8’) |
s.encode('utf-8') |
Dictionary (字典) 常用方法 (Mutable)
| 方法 | 用途/說明 | 參數 | 範例 |
|---|---|---|---|
.get() |
安全存取 | (key, default) (找不到時回傳 default) |
d.get('key', 0) |
.keys() |
獲取所有鍵 | 無 | d.keys() |
.values() |
獲取所有值 | 無 | d.values() |
.items() |
獲取鍵值對 | 無 | d.items() |
.update() |
合併/更新 | other_dict |
d.update({'c': 3}) |
.pop() |
按鍵移除 | (key, [default]) |
d.pop('a') |
Set (集合) 常用方法 (Mutable)
| 方法 | 用途/說明 | 參數 | 範例 |
|---|---|---|---|
.add() |
新增元素 | x (單一元素) |
s.add(5) |
.remove() |
移除元素 | x (若元素不存在會拋出 KeyError) |
s.remove('a') |
.discard() |
安全移除 | x (若元素不存在不會拋出錯誤) |
s.discard('a') |
| / .union() |
聯集 | other_set |
s1 | s2 |
& / .intersection() |
交集 | other_set |
s1 & s2 |
流程控制、迴圈與函數基礎
核心: 掌握如何控制程式碼的執行順序,並定義可重複使用的邏輯單元。
邏輯結構與流程控制
- 條件判斷:
if,elif,else結構。- Python 風格: 強制縮排 (Indentation) 而非大括號,提高了程式碼可讀性。
- 條件表達式 (三元運算符): 簡潔地將
if/else寫入一行。- 語法:
value_if_true if condition else value_if_false - 範例:
status = "Pass" if score >= 60 else "Fail"
- 語法:
疊代機制與迴圈 (Loops)
for迴圈: 用於對序列、容器等 可疊代 (Iterable) 物件進行遍歷。- 關鍵字:
break(跳出整個迴圈)、continue(跳過當前疊代)。
- 關鍵字:
while迴圈: 用於滿足特定條件時重複執行區塊,通常用於無法預知疊代次數的情況。- Python 特色:迴圈的
else子句- 用途: 當迴圈正常結束(即沒有被
break語句終止)時,else區塊才會執行。
- 用途: 當迴圈正常結束(即沒有被
💻 for...else 範例:
for item in my_list:
if item < 0:
print("找到負數!")
break
else:
print("列表中沒有發現負數。") # 只有迴圈正常結束才執行
異常處理與錯誤捕捉 (Exception Handling)
核心: 程式運行時的錯誤稱為異常 (Exception)。使用
try...except機制,是為了讓程式在面對預期錯誤時,能夠優雅地失敗 (Fail Gracefully)。
-
異常與錯誤:
- SyntaxError (語法錯誤): 程式碼本身寫錯,編譯器/直譯器會立刻報錯,程式無法啟動。
- Exception (運行時異常): 語法正確,但在運行時發生問題,如
ZeroDivisionError(除以零) 或KeyError(字典中找不到鍵)。
-
基礎結構:
try...except...else...finally
| 關鍵字 | 用途 | 執行時機 |
|---|---|---|
try |
放置可能引發異常的程式碼。 | 總是先執行。 |
except |
捕捉並處理特定類型的異常。 | 僅當 try 區塊發生異常時執行。 |
else |
放置沒有發生異常時才執行的程式碼。 | 僅當 try 區塊成功執行完畢時執行。 |
finally |
放置無論是否發生異常,都一定會執行的程式碼。 | 常用於資源清理,如關閉文件或資料庫連線。 |
💻 範例 (安全除法):
try:
result = 10 / num # 潛在的 ZeroDivisionError
except ZeroDivisionError as e:
print(f"錯誤!發生除以零的錯誤: {e}")
except Exception as e:
print(f"發生其他未知錯誤: {e}")
else:
print(f"計算成功,結果是: {result}")
finally:
print("--- 流程結束 ---")
函式定義:參數詳解 (args, kwargs)
核心: 掌握四種參數類型 (位置、關鍵字、args、*kwargs) 的傳遞順序和應用場景,是編寫靈活函式的基礎。
① 四種參數類型 (順序嚴格)
在 Python 函式定義中,參數必須嚴格按照以下順序排列:
- 位置/關鍵字參數 (Positional or Keyword): 最常見的參數,可以通過位置或名稱傳遞。
*args(可變位置參數): 用於接收不定數量的位置參數。- 單獨的關鍵字參數 (Keyword-Only): 必須通過名稱傳遞,即使傳遞時在正確的位置也不能省略名稱。
**kwargs(可變關鍵字參數): 用於接收不定數量的關鍵字參數。
| 參數符號 | 用途 | 接收的數據類型 | 範例應用 |
|---|---|---|---|
| (無) | 必須傳遞的參數 | 任何單一值 | def f(a, b): |
*args |
接收不定量的位置參數 | Tuple | def f(*args): |
**kwargs |
接收不定量的關鍵字參數 | Dictionary | def f(**kwargs): |
② 應用:*args (可變位置參數)
- 接收方式: 函式會將傳入的多餘位置參數,打包成一個 Tuple 賦予
args。 - 主要用途: 處理可變數量的值,例如計算任意多個數字的總和。
💻 範例:
def sum_all(*numbers):
return sum(numbers)
sum_all(1, 2, 3, 4) # numbers 會是 (1, 2, 3, 4)
③ 應用:**kwargs (可變關鍵字參數)
- 接收方式: 函式會將傳入的多餘關鍵字參數 (Key=Value),打包成一個 Dictionary 賦予 kwargs。
- 主要用途: 傳遞額外的配置或可選參數,常用於類別初始化或 API 呼叫。
💻 範例:
def create_profile(name, **details):
# details 會是 {'age': 30, 'city': 'Taipei'}
profile = {'name': name}
profile.update(details)
return profile
④ 綜合範例:參數展開 (Unpacking)
- 用途: 在呼叫函式時,將 Tuple/List 用 * 展開成位置參數,或將 Dictionary 用 ** 展開成關鍵字參數。
- 目的: 提高程式碼的靈活性,適用於數據來源是容器的情況。
💻 範例:
# 假設我們有一個數據列表和一個配置字典
data = [10, 20]
config = {'c': 30, 'd': 40}
def process(a, b, c, d):
print(a + b + c + d)
# 參數展開
process(*data, **config) # 相當於 process(10, 20, c=30, d=40)
⑤ 程式碼規範:型別提示 (Type Hinting)
- 用途: 這是 Python 3.5+ 引入的標準,用來提示 (Hint) 變數、參數和返回值應該是什麼型別。
- 重點: 型別提示不會影響程式運行,但它用於:提高可讀性 和 靜態分析。
- 容器的引入: 像
List或Dict這樣的容器型別,需要從標準庫typing中引入。
💻 語法範例:
from typing import List, Optional, Tuple
# 提示:接受一個整數列表,並回傳一個字串(或 None)
def process_data(
data_list: List[int], # 參數 data_list 應為 int 的 List
limit: Optional[int] = None # 參數 limit 可為 int 或 None (Optional)
) -> str: # 函式回傳值應為 str
if limit is None:
return f"Processed {len(data_list)} items."
# ...
匿名函數、常用函數與高階函式
核心: Lambda 是用於即時創建規則的工具;高階函式則是應用這些規則來轉換數據的流程。
① 匿名函數 (Lambda) 的特性
- 語法:
lambda arguments: expression。 - 限制: 只能包含一個單一的 表達式 (Expression),適用於一次性、簡單的邏輯。
💻 範例:
# 1. 定義一個 lambda 函式,它接受 x, y 兩個參數,回傳 x + y 的結果
add_numbers = lambda x, y: x + y
# 2. 立即呼叫並計算
result = add_numbers(10, 5)
print(result)
# 輸出: 15
② 核心區別:高階函式 (HOF) 的本質
HOF 接受 函式本身 (Code) 作為參數 (如 key= 或 function=),執行抽象的數據轉換,這是它與一般函式的最大差別。
- 參數意義 (Key/Function):HOF 透過關鍵字參數,如 key= 或 function=,來接收你傳入的 lambda 或其他 def 函式。
- 以 sorted() 為例: 你傳入 key=lambda x: x[‘score’],就像給了 sorted 一個「計算分數」的指令,它會根據這個指令執行排序,而不是根據預設規則。
③ 常用函數、高階函數表
| 函式 | 類型 | 關鍵參數與返回值 | 應用與 HOF 特性 |
|---|---|---|---|
range() |
疊代工具 | 參數: range(start, stop, step)。返回疊代器。 |
用於生成序列,是 for 迴圈最常見的伙伴。 |
enumerate() |
疊代工具 | 參數: enumerate(iterable, start=0)。返回 (索引, 值)。 |
用於同時獲取元素和其位置。 |
zip() |
疊代工具 | 參數: zip(iterable1, iterable2, ...)。返回多序列組合的 Tuple。 |
快速合併多組數據進行同時遍歷。 |
sorted() |
高階函式 (HOF) | 參數: key=func, reverse=bool。返回新的已排序列表。 |
HOF 特性: key 參數接受 lambda來自定義排序邏輯。 |
map() |
高階函式 (HOF) | 參數: map(function, iterable)。返回映射結果的疊代器。 |
HOF 特性: 將 function 應用到序列中的每個元素。 |
filter() |
高階函式 (HOF) | 參數: filter(function, iterable)。返回過濾後的疊代器。 |
HOF 特性: function 必須回傳布林值,用於決定元素去留。 |
| sum() | 聚合計算 | “sum(iterable, start=0)。回傳數字。” | 快速計算可疊代物件的總和。 |
| min()/max() | 聚合計算 | min(iterable)。回傳數字。 | 快速找出最小值/最大值。 |
| all()/any() | 布林檢查 | all/any(iterable)。回傳布林值。 | 檢查所有/任一元素的真值性 (Truthiness)。 |
| isinstance() | 類型檢查 | “isinstance(object, classinfo)。回傳布林值。” | 運行時檢查物件是否屬於某類型 (支援檢查多類型)。 |
| int()/str()/list() | 類型轉換 | (單一參數)。回傳新的類型物件。 | 用於數據型別之間的快速轉換。 |
| print() | 基礎 I/O | “print(…, sep=’ ‘, end=’\n’)。回傳 None。” | 輸出信息到終端。 |
| input() | 基礎 I/O | input(prompt)。回傳用戶輸入的字串。 | 接收用戶輸入 (注意:返回值永遠是 str)。 |
④函數說明跟範例
-
range() (序列生成器)
- 參數:
range(stop)或range(start, stop, step)。 - 預設值:
start預設為 0;step預設為 1。 -
用途: 產生連續的整數序列,返回一個疊代器。
-
💻 範例:
- 參數:
# 只給一個參數:stop=5。從 0 開始,步進 1
for i in range(5):
print(i, end=' ')
# 輸出: 0 1 2 3 4
# 從 10 倒數到 2 (不包含 0),步進為 -2
for i in range(10, 0, -2):
print(i, end=' ')
# 輸出: 10 8 6 4 2
- enumerate() (疊代計數器)
- 參數: enumerate(iterable, start=0)。
- 用途: 在遍歷時同時回傳 (索引, 值) 的 Tuple。
- 💻 範例:
colors = ['red', 'green', 'blue']
for i, color in enumerate(colors, start=1):
print(f"No.{i}: {color}")
# 輸出: No.1: red, No.2: green, No.3: blue
- zip() (序列組合器)
- 參數: zip(iterable1, iterable2, …)。
- 用途: 將多個序列按索引位置打包成 Tuple 的疊代器。
- 💻 範例:
names = ['Alice', 'Bob']
scores = [90, 85]
for name, score in zip(names, scores):
print(f"{name} 獲得 {score} 分")
# 輸出: Alice 獲得 90 分, Bob 獲得 85 分
- sorted() (高階函式 HOF)
- HOF 特性:接受 key=func 參數,用來指定排序時計算元素權重的規則。
- 參數: sorted(iterable, key=func, reverse=bool)。
- 用途: 返回新的已排序列表。
- 💻 範例:
words = ["Apple", "banana", "Cherry"]
# key=str.lower 讓 sorted 忽略大小寫
sorted_list = sorted(words, key=str.lower)
print(sorted_list)
# 輸出: ['Apple', 'banana', 'Cherry']
- map() (高階函式 HOF)
- HOF 特性:接受 function 參數,將該函式一次性應用到可疊代物件的每個元素。
- 參數: map(function, iterable)。
- 用途: 返回映射結果的疊代器。
- 💻 範例:
numbers = [1, 2, 3]
# 使用 lambda 定義轉換規則 (x * 2)
doubled = list(map(lambda x: x * 2, numbers))
print(doubled)
# 輸出: [2, 4, 6]
- filter() (高階函式 HOF)
- HOF 特性:接受 function 參數,該函式必須回傳 True 或 False,決定元素的去留。
- 參數: filter(function, iterable)。
- 用途: 返回過濾結果的疊代器。
- 💻 範例:
data = [5, 10, 20]
# 使用 lambda 定義過濾規則 (大於 10)
filtered = list(filter(lambda x: x > 10, data))
print(filtered)
# 輸出: [20]
- sum() / min() / max() (聚合計算)
- 參數: sum(iterable, start=0);min(iterable)。
- 用途: 快速計算可疊代物件的總和、最小值或最大值。
- 💻 範例:
numbers = [10, 5, 20]
total = sum(numbers) # 輸出: 35
minimum = min(numbers) # 輸出: 5
maximum = max(numbers) # 輸出: 20
- all() / any() (布林檢查)
- 參數: all(iterable);any(iterable)。
- 用途: 對可疊代物件中的所有或任一元素的真值性 (Truthiness) 進行檢查。這是高效且 Pythonic 的條件檢查方法。
- 💻 範例:
scores = [80, 90, 75]
# all:檢查所有分數是否都大於 70 (True)
all_pass = all(score > 70 for score in scores)
# any:檢查是否有任何一個分數為 0 (False)
has_zero = any(score == 0 for score in scores)
print(f"全部通過: {all_pass}") # 輸出: True
print(f"有零分: {has_zero}") # 輸出: False
- isinstance() (類型檢查)
- 參數: isinstance(object, classinfo)。
- 用途: 檢查一個物件是否屬於某個類別或某個型別的實例。在設計可接受多種類型輸入的函式時非常有用。
- 💻 範例:
data = [1, 'hello', 3.0]
is_string = isinstance(data[1], str) # 輸出: True
is_int_or_float = isinstance(data[0], (int, float)) # 檢查是否為 int 或 float
print(f"是字串: {is_string}")
print(f"是數字: {is_int_or_float}")
- 類型轉換 (Type Conversion)
- 主要函數: str(), int(), float(), list(), tuple(), dict(), set()。
- 用途: 這是 Python 中最常用的操作之一,用於將數據從一種型別轉換為另一種型別。
- 💻 範例:
number_str = "123"
# 1. 轉為 int 進行計算
result_int = int(number_str) + 7
my_tuple = (1, 2, 3)
# 2. 轉為 list 進行修改 (因為 list 可變)
my_list = list(my_tuple)
my_list.append(4)
print(result_int) # 輸出: 130
print(my_list) # 輸出: [1, 2, 3, 4]
- 基礎 I/O
- 主要函數: print(), input()。
- 用途: 程式與用戶互動的最基本方式。
- 💻 範例:
# input() 接收的永遠是字串 (str)
user_name = input("請輸入你的名字: ")
print(f"你好,{user_name}!")
類別 (Class) 基礎架構 (物件導向)
核心: 類別是藍圖,用於定義一種物件的屬性 (Attributes) 和行為 (Methods)。物件導向 (OOP) 的三大支柱:封裝 (Encapsulation)、繼承 (Inheritance) 和 多型 (Polymorphism)。
類別與實例 (Class vs. Instance)
- 類別 (Class): 定義資料結構和方法的模板。使用
class關鍵字定義。 - 實例/物件 (Instance/Object): 根據類別藍圖創建的具體實體。每個實例在記憶體中都有自己獨立的屬性值。
- 創建實例:
obj = ClassName()
- 創建實例:
核心構造函數 (__init__)
- 用途: 實例化 (Instantiation) 時自動調用的特殊方法。用於對新創建的物件進行初始化,即賦予它初始屬性。
- 參數: 必須接收第一個參數
self,它代表正在被建立的那個物件本身。 - 屬性定義: 通過
self.attribute = value在物件上設置實例屬性。
💻 範例:
class Dog:
# 類別屬性:所有實例共享
species = "Canis familiaris"
def __init__(self, name, age):
# 實例屬性:每個物件獨有
self.name = name
self.age = age
def bark(self):
# 實例方法:定義物件的行為
print(f"{self.name} 汪汪叫!")
封裝 (Encapsulation)
-
定義: 將資料(屬性)和操作這些資料的代碼(方法)捆綁在一起,並控制對資料的存取。
-
Python 風格: Python 沒有嚴格的 private 關鍵字,而是使用命名約定來暗示封裝性:
- 單底線 (_attribute): 這是對開發者的弱警告:這個屬性是內部使用的,不應直接存取,但技術上仍可存取。
- 雙底線 (__attribute): 觸發名稱修飾 (Name Mangling),使外部存取更困難,但目的是防止子類別覆蓋父類別的屬性,而非真正的隱藏。
繼承 (Inheritance)
- 定義: 允許一個類別 (子類別/Child Class) 繼承另一個類別 (父類別/Parent Class) 的屬性和方法。
- 語法: class ChildClass(ParentClass):
- super() 函數:用於調用父類別中的方法,特別是在子類別重寫 (override) init 或其他方法時,確保父類別的初始化邏輯得以執行。
💻 範例(繼承):
class Puppy(Dog):
def __init__(self, name, age, color):
# 1. 調用父類別的 __init__ 進行初始化
super().__init__(name, age)
# 2. 增加自己的特有屬性
self.color = color
# 重寫父類別的 bark 方法
def bark(self):
print("小狗嗚嗚叫...")
特殊方法 (Dunder Methods)
- 定義: 以雙底線開始和結束的方法(如 init)。它們定義了類別在特定情境下的行為。
- 常用 Dunder Methods:
- str(self):定義物件的用戶友好字串表示 (供 print() 函數使用)。
- repr(self):定義物件的程式碼級別字串表示 (供開發者使用)。
💻 範例 (str):
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
# 定義 print(p) 時的輸出格式
return f"Point({self.x}, {self.y})"
1.2 核心原理與進階機制
深入理解 Python 的設計哲學,從會用進化到能設計。
1.2.1 閉包、裝飾器 (Decorator) 原理與實戰
- 原理: 閉包 (Closure) 如何形成;裝飾器的執行流程。
- 實戰: 手寫一個帶參數或類別型態的 Decorator。
1.2.2 迭代器 (Iterator) 與生成器 (Generator)
- 原理:
__iter__與__next__的協議;yield關鍵字在記憶體上的優勢。
1.2.3 深入物件導向 (OOP Deep Dive)
- 魔法方法:
__str__,__repr__,__call__等的用法。 - 繼承與多型: 繼承的原理與方法重載/覆蓋。
1.2.4 協程與非同步 (Async/Await)
- 原理: 事件循環 (Event Loop) 的概念;
async/await如何在單線程中實現並行。
1.3 應用優化與程式碼實踐
專注於開發時的規範、效率與生態系。
1.3.1 函式編程與 Type Hinting
- 進階函式:
map/filter/zip的高效使用。 - 規範: 使用
typing模組進行型別註記。
1.3.2 標準庫應用 (Dataclass, Time, OS)
- 效率: 使用
dataclasses簡化 DTO (Data Transfer Object) 或配置檔。
1.3.3 Log、Debug 與測試基礎
- 錯誤追蹤: 標準
logging模組的配置與使用。 - 除錯: PDB 或 VS Code Debugger 的高效使用技巧。
⚔️ 資料結構與演算法
待補充
🗄️ 資料庫與 SQL 實戰
待補充
🏗️ Web 後端框架
待補充
🛠️ Linux 與開發工具箱
待補充
⚙️ 基礎設施與部署維運
待補充
⚛️ 前端與客戶端開發
待補充