Yoru Karu Studio

程式設計學習筆記 | 生活心得

演算法基礎:空間複雜度完全指南

什麼是空間複雜度? 空間複雜度(Space Complexity)描述了演算法執行時所需的記憶體空間如何隨著輸入規模增長。它回答了一個關鍵問題:「當資料量變大時,程式需要多少記憶體?」 為什麼空間複雜度很重要? # 情境:處理一個 10GB 的檔案 # 方法 1:全部載入記憶體(可能造成記憶體不足) def process_file_v1(filename): with open(filename, 'r') as f: content = f.read() # 需要 10GB 記憶體! return content.upper() # 方法 2:逐行處理(記憶體使用量固定) def process_file_v2(filename): result = [] with open(filename, 'r') as f: for line in f: # 一次只載入一行 result.append(line.upper()) return ''.join(result) # 方法 3:串流處理(最省記憶體) def process_file_v3(filename, output_filename): with open(filename, 'r') as f_in, open(output_filename, 'w') as f_out: for line in f_in: f_out.write(line.upper())空間複雜度的組成 1. 輸入空間 演算法輸入資料佔用的空間(通常不計入額外空間)。

演算法基礎:時間複雜度完全指南

什麼是時間複雜度? 時間複雜度(Time Complexity)是用來描述演算法執行時間如何隨著輸入規模增長的數學模型。簡單來說,它回答了一個問題:「當資料量變大時,程式會跑多久?」 為什麼需要時間複雜度? 想像你要從一本電話簿中找到某個人的電話號碼: # 方法 1:從頭翻到尾(線性搜尋) def linear_search(phone_book, name): for entry in phone_book: if entry.name == name: return entry.phone return None # 方法 2:利用排序特性(二分搜尋) def binary_search(phone_book, name): left, right = 0, len(phone_book) - 1 while left <= right: mid = (left + right) // 2 if phone_book[mid].name == name: return phone_book[mid].phone elif phone_book[mid].name < name: left = mid + 1 else: right = mid - 1 return None當電話簿有 1000 個號碼時,差異可能不明顯。但如果有 100 萬個號碼呢?這就是為什麼我們需要時間複雜度分析。

Django 面試準備 11-3:競態條件處理

11-3. 競態條件處理(Race Condition Handling) 📌 什麼是競態條件? 簡單說: 多個線程同時操作共享數據,結果取決於執行順序 定義: 當兩個或多個線程並發訪問共享資源,且至少有一個線程進行寫操作時,如果沒有適當的同步機制,程序的行為將變得不可預測。 🔍 經典的競態條件示例 銀行轉帳問題 # ❌ 有競態條件的代碼 class BankAccount: def __init__(self, balance=0): self.balance = balance def withdraw(self, amount): # 步驟 1: 檢查餘額 if self.balance >= amount: # 步驟 2: 計算新餘額 new_balance = self.balance - amount # 步驟 3: 更新餘額 self.balance = new_balance return True return False account = BankAccount(balance=100)競態條件發生: 時間 Thread 1 (提款 80) Thread 2 (提款 80) balance T1 檢查: 100 >= 80 ✓ T2 檢查: 100 >= 80 ✓ 100 T3 計算: 100 - 80 = 20 T4 計算: 100 - 80 = 20 100 T5 寫入: balance = 20 T6 寫入: balance = 20 20 結果:兩次提款共 160 元,但餘額只減少 80 元!💥 正確應該是:餘額不足,第二次提款失敗 🎯 Django 中的常見競態條件 場景 1:庫存扣減 # models.

Django 面試準備 11-2:全局變量陷阱

11-2. 全局變量陷阱(Global Variable Pitfalls) 📌 為什麼全局變量危險? 簡單說: 多個線程共享同一個全局變量,會互相干擾 核心問題: 🔴 數據混淆:線程 A 的數據被線程 B 覆蓋 🔴 競態條件:並發修改導致數據不一致 🔴 難以調試:問題隨機出現,難以復現 🔴 陷阱 1:模塊級變量 問題演示 # views.py # ❌ 危險的全局變量 current_user = None def login_view(request): global current_user current_user = request.user # 設置全局變量 return HttpResponse(f"Logged in as {current_user.username}") def profile_view(request): global current_user # 期望獲取當前用戶 username = current_user.username return HttpResponse(f"Profile of {username}")問題場景 時間線: T1 Thread 1: login_view() current_user = User("Alice") T2 Thread 2: login_view() current_user = User("Bob") ← 覆蓋了! T3 Thread 1: profile_view() 讀取 current_user → 得到 User("Bob") ❌(期望 Alice) T4 Thread 2: profile_view() 讀取 current_user → 得到 User("Bob") ✓後果: Alice 看到了 Bob 的資料!嚴重的安全問題!

Django 面試準備 11-1:Django 線程安全機制

11-1. Django 線程安全機制(Thread Safety Mechanism) 📌 什麼是線程安全? 簡單說: 多個線程同時訪問同一資源時,不會出現數據錯誤或不一致 定義: 線程安全是指在多線程環境下,程序能夠正確地處理多個線程同時訪問共享資源,而不會導致數據競爭或不一致的狀態。 🔍 Django 的多線程環境 WSGI 服務器的線程模式 用戶請求 → WSGI 服務器 → Django 應用 WSGI 服務器(如 Gunicorn): ┌────────────────────────────────┐ │ Worker Process 1 │ │ ├─ Thread 1 → Request A │ │ ├─ Thread 2 → Request B │ │ └─ Thread 3 → Request C │ ├────────────────────────────────┤ │ Worker Process 2 │ │ ├─ Thread 1 → Request D │ │ ├─ Thread 2 → Request E │ │ └─ Thread 3 → Request F │ └────────────────────────────────┘ Django 請求處理流程 # 每個請求在獨立線程中處理 def handle_request(request): # 線程 1 Thread-1: 處理 Request A ├─ 創建 HttpRequest 對象 ├─ 執行中間件 ├─ 調用 View 函數 ├─ 渲染模板 └─ 返回 HttpResponse # 線程 2(同時進行) Thread-2: 處理 Request B ├─ 創建 HttpRequest 對象 ├─ 執行中間件 ├─ 調用 View 函數 ├─ 渲染模板 └─ 返回 HttpResponse關鍵: 每個請求都在獨立的線程中處理,互不干擾

Django 面試準備 10-4:查詢性能分析工具

10-4. 查詢性能分析工具(Query Performance Tools) 📌 為什麼需要性能分析工具? 問題: 如何發現查詢性能問題? 🔍 發現 N+1 查詢 📊 識別慢查詢 ⚡ 優化瓶頸 📈 監控性能 🔧 工具 1:Django Debug Toolbar 安裝配置 pip install django-debug-toolbar# settings.py INSTALLED_APPS = [ ... 'debug_toolbar', ] MIDDLEWARE = [ 'debug_toolbar.middleware.DebugToolbarMiddleware', ... ] INTERNAL_IPS = [ '127.0.0.1', ] # 可選配置 DEBUG_TOOLBAR_CONFIG = { 'SHOW_TOOLBAR_CALLBACK': lambda request: DEBUG, 'SQL_WARNING_THRESHOLD': 100, # 查詢時間超過 100ms 警告 } # urls.py from django.urls import include, path urlpatterns = [ .
0%