好的,在掌握了 Python 的基本語法後,接下來我們深入探討一些更進階但非常重要的概念:物件導向程式設計 (OOP)、模組與套件、錯誤處理、文件操作、生成器 (Generators)、裝飾器 (Decorators) 和上下文管理器 (Context Managers)。這些概念將幫助你寫出更結構化、可維護、高效且具備錯誤處理能力的 Python 程式碼。
Python 進階概念
1. 物件導向程式設計 (Object-Oriented Programming, OOP)
OOP 是一種程式設計範式,它將數據和處理數據的函數組織成稱為「物件」的獨立單元。主要概念包括:
- 類別 (Class): 藍圖或模板,定義了物件的屬性 (attributes) 和行為 (methods)。
- 物件 (Object): 類別的一個實例。
- 封裝 (Encapsulation): 將數據(屬性)和操作數據的函數(方法)綁定在一起,並對外部隱藏其內部實現細節。
- 繼承 (Inheritance): 允許一個類別(子類別)從另一個類別(父類別)繼承屬性和方法,實現代碼重用。
- 多型 (Polymorphism): 允許不同的類別以自己的方式實現共同的接口或方法,表現出不同的行為。
範例: 模擬租車系統中的車輛
class Vehicle:
"""
車輛的基底類別
"""
def __init__(self, make, model, year, daily_rate):
# 實例屬性
self.make = make
self.model = model
self.year = year
self.daily_rate = daily_rate
self.is_available = True
def display_info(self):
"""顯示車輛基本資訊"""
print(f"品牌: {self.make}, 型號: {self.model}, 年份: {self.year}")
print(f"每日租金: ${self.daily_rate:.2f}, 可用狀態: {self.is_available}")
def rent_vehicle(self):
"""租用車輛"""
if self.is_available:
self.is_available = False
print(f"{self.make} {self.model} 已成功租用。")
return True
else:
print(f"{self.make} {self.model} 目前不可用。")
return False
def return_vehicle(self):
"""歸還車輛"""
if not self.is_available:
self.is_available = True
print(f"{self.make} {self.model} 已成功歸還。")
return True
else:
print(f"{self.make} {self.model} 本來就是可用狀態。")
return False
class Car(Vehicle): # Car 繼承自 Vehicle
"""
汽車類別
"""
def __init__(self, make, model, year, daily_rate, num_doors, fuel_type):
super().__init__(make, model, year, daily_rate) # 呼叫父類別的建構子
self.num_doors = num_doors
self.fuel_type = fuel_type
def display_info(self): # 多型:重寫父類別的方法
super().display_info() # 呼叫父類別的 display_info
print(f"門數: {self.num_doors}, 燃料類型: {self.fuel_type}")
class Motorcycle(Vehicle): # Motorcycle 繼承自 Vehicle
"""
摩托車類別
"""
def __init__(self, make, model, year, daily_rate, engine_size):
super().__init__(make, model, year, daily_rate)
self.engine_size = engine_size
def display_info(self): # 多型:重寫父類別的方法
super().display_info()
print(f"引擎排氣量: {self.engine_size}cc")
# 創建物件實例
car1 = Car("Toyota", "Camry", 2022, 50.00, 4, "汽油")
bike1 = Motorcycle("Honda", "CBR500R", 2023, 30.00, 500)
print("--- 汽車資訊 ---")
car1.display_info()
car1.rent_vehicle()
car1.rent_vehicle() # 再次租用,會提示不可用
print("\n--- 摩托車資訊 ---")
bike1.display_info()
bike1.rent_vehicle()
bike1.return_vehicle()
2. 模組 (Modules) 與 套件 (Packages)
- 模組 (Module): 一個 Python 檔案 (
.py
結尾),包含 Python 程式碼(變數、函數、類別)。它允許你將程式碼組織成邏輯單元,提高可讀性和可維護性。 - 套件 (Package): 一個包含多個模組的目錄,該目錄必須包含一個名為
__init__.py
的特殊檔案(在 Python 3.3+,這個檔案可以是空的,但在舊版本中是必需的,用來標記該目錄為 Python 套件)。套件可以包含子套件。
範例: 模組與套件的結構與使用
假設你有以下目錄結構:
my_rental_app/
├── main.py
├── vehicles/
│ ├── __init__.py
│ ├── car.py
│ └── motorcycle.py
└── utils/
├── __init__.py
└── helpers.py
vehicles/car.py
:
# vehicles/car.py
from ..vehicles import Vehicle # 相對導入
class Car(Vehicle):
def __init__(self, make, model, year, daily_rate, num_doors, fuel_type):
super().__init__(make, model, year, daily_rate)
self.num_doors = num_doors
self.fuel_type = fuel_type
def display_info(self):
super().display_info()
print(f"門數: {self.num_doors}, 燃料類型: {self.fuel_type}")
utils/helpers.py
:
# utils/helpers.py
def format_currency(amount, currency_code="USD"):
"""格式化金額"""
return f"{currency_code} {amount:.2f}"
main.py
:
# main.py
from vehicles.car import Car # 從套件.模組導入類別
from utils.helpers import format_currency # 從套件.模組導入函數
# 或者直接導入模組,然後使用 module.Class/function
# import vehicles.car
# import utils.helpers
my_car = Car("Tesla", "Model 3", 2024, 70.00, 4, "電動")
my_car.display_info()
price = 125.756
formatted_price = format_currency(price, "TWD")
print(f"原始價格: {price}, 格式化後: {formatted_price}")
導入方式:
import module_name
: 導入整個模組。使用時需module_name.function_name()
。from module_name import function_name, ClassName
: 導入模組中的特定內容。直接使用function_name()
。from package_name.module_name import ClassName
: 從套件中的模組導入。import package_name.module_name as alias
: 導入並賦予別名。
3. 錯誤處理 (Error Handling)
程式在執行過程中可能會遇到錯誤(異常)。Python 使用 try-except-finally
塊來處理這些錯誤,防止程式崩潰。
try
: 放置可能拋出異常的程式碼。except
: 捕獲並處理指定類型的異常。可以有多個except
塊來處理不同類型的異常。else
: (可選) 如果try
塊中沒有發生異常,則執行else
塊中的程式碼。finally
: (可選) 無論try
塊中是否發生異常,finally
塊中的程式碼都會被執行。常用於資源清理(如關閉文件或資料庫連接)。
範例:
def safe_divide(numerator, denominator):
try:
result = numerator / denominator
except ZeroDivisionError: # 捕獲除以零的錯誤
print("錯誤:除數不能為零!")
return None
except TypeError: # 捕獲類型錯誤
print("錯誤:輸入必須是數字!")
return None
except Exception as e: # 捕獲其他所有異常
print(f"發生未知錯誤: {e}")
return None
else:
# 如果 try 塊沒有異常,則執行這裡
print("除法成功!")
return result
finally:
# 無論如何都會執行
print("除法操作完成。")
print(safe_divide(10, 2)) # 輸出: 除法成功!\n 5.0
print("-" * 20)
print(safe_divide(10, 0)) # 輸出: 錯誤:除數不能為零!\n 除法操作完成。 None
print("-" * 20)
print(safe_divide(10, "a")) # 輸出: 錯誤:輸入必須是數字!\n 除法操作完成。 None
4. 文件操作 (File Operations)
讀寫文件是常見操作。Python 提供內建函數 open()
來處理文件。
- 模式:
'r'
:讀取模式(預設)。'w'
:寫入模式(如果文件不存在則創建,存在則清空)。'a'
:追加模式(如果文件不存在則創建,存在則在末尾追加)。'x'
:獨占創建模式(如果文件已存在則報錯)。't'
:文本模式(預設)。'b'
:二進位模式。'+'
:讀寫模式。
- 最佳實踐:
with
語句: 使用with open(...) as f:
語句可以確保文件在使用完畢後自動關閉,即使發生錯誤也不會造成資源洩漏。
範例:
file_name = "example.txt"
# 寫入文件
with open(file_name, 'w', encoding='utf-8') as f:
f.write("這是第一行內容。\n")
f.write("這是第二行內容,包含中文。\n")
print(f"'{file_name}' 已寫入。")
# 讀取文件
with open(file_name, 'r', encoding='utf-8') as f:
content = f.read() # 讀取所有內容
print(f"\n'{file_name}' 內容:\n{content}")
# 逐行讀取文件
with open(file_name, 'r', encoding='utf-8') as f:
print(f"\n'{file_name}' 逐行內容:")
for line in f:
print(line.strip()) # strip() 移除行尾的換行符
# 追加內容到文件
with open(file_name, 'a', encoding='utf-8') as f:
f.write("這是追加的第三行。\n")
print(f"\n'{file_name}' 已追加內容。")
# 再次讀取確認
with open(file_name, 'r', encoding='utf-8') as f:
print(f"\n'{file_name}' 最新內容:\n{f.read()}")
5. 生成器 (Generators)
生成器是一種特殊類型的迭代器,它不會一次性在記憶體中生成所有數據,而是按需生成。這對於處理大量數據流或無限序列非常高效。
- 關鍵字
yield
: 函數中包含yield
語句就會變成一個生成器函數。每次呼叫yield
時,函數會暫停執行並返回一個值,下次迭代時從上次暫停的地方繼續。
範例:
def fibonacci_sequence(n):
"""生成前 n 個費波那契數"""
a, b = 0, 1
for _ in range(n):
yield a # 每次呼叫 next() 時返回 a
a, b = b, a + b # 更新 a 和 b
# 使用生成器
fib_gen = fibonacci_sequence(10)
print("透過 next() 逐一獲取:")
print(next(fib_gen)) # 輸出: 0
print(next(fib_gen)) # 輸出: 1
print(next(fib_gen)) # 輸出: 1
print("\n透過 for 迴圈遍歷生成器:")
for num in fibonacci_sequence(5):
print(num)
# 輸出:
# 0
# 1
# 1
# 2
# 3
# 生成器表達式 (類似列表推導式)
squares_gen = (x * x for x in range(5))
print(f"\n生成器表達式: {squares_gen}") # 輸出: <generator object <genexpr> at ...>
print(list(squares_gen)) # 輸出: [0, 1, 4, 9, 16] (一旦轉換成列表,生成器就被耗盡)
優勢:
- 記憶體效率: 不需要將所有數據載入記憶體。
- 惰性求值: 數據只有在需要時才生成。
- 處理無限序列。
6. 裝飾器 (Decorators)
裝飾器是一種在不修改原函數程式碼的情況下,動態地給函數(或類別)添加功能的語法糖。本質上,裝飾器是一個函數,它接收一個函數作為參數,並返回一個新的函數。
- 語法: 使用
@decorator_name
放在函數定義上方。
範例: 記錄函數執行時間的裝飾器
import time
def timer(func):
"""
一個裝飾器,用於測量函數的執行時間。
"""
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs) # 呼叫原始函數
end_time = time.time()
print(f"函數 '{func.__name__}' 執行時間: {end_time - start_time:.4f} 秒")
return result
return wrapper
@timer # 這等同於 my_slow_function = timer(my_slow_function)
def my_slow_function(n):
"""一個模擬耗時操作的函數。"""
sum_val = 0
for i in range(n):
sum_val += i * i
time.sleep(0.0001) # 模擬一些耗時操作
return sum_val
@timer
def greet(name):
print(f"Hello, {name}!")
print(f"計算結果: {my_slow_function(1000)}")
greet("Decorator User")
優勢:
- 代碼重用: 將通用功能(如日誌、性能測量、認證、權限檢查)應用於多個函數。
- 代碼清晰: 減少重複程式碼,使函數的邏輯更專注於其核心職責。
7. 上下文管理器 (Context Managers)
上下文管理器允許你定義一個資源的獲取和釋放邏輯,確保資源在完成操作後被正確關閉或清理。最常見的用法是 with
語句。
- 核心概念:
__enter__(self)
方法:在進入with
塊時被呼叫,通常返回要使用的資源。__exit__(self, exc_type, exc_val, exc_tb)
方法:在離開with
塊時被呼叫,即使發生異常也會被呼叫,用於清理資源。
- 使用
contextlib
模組的@contextmanager
裝飾器: 更簡單地創建上下文管理器。
範例 1: 使用 with open(...)
(內建上下文管理器)
# 文件操作就是一個典型的上下文管理器應用
with open("test.txt", "w") as f:
f.write("This is a test.")
# 文件會在這個 with 塊結束時自動關閉
print("文件 'test.txt' 已寫入並自動關閉。")
範例 2: 自定義上下文管理器 (模擬資料庫連接)
class DatabaseConnection:
def __init__(self, db_name):
self.db_name = db_name
self.connection = None
def __enter__(self):
print(f"連接到資料庫: {self.db_name}...")
# 這裡應該是實際的資料庫連接邏輯
self.connection = f"Connected to {self.db_name}" # 模擬連接對象
return self.connection # 返回連接對象,with as variable 會接收到它
def __exit__(self, exc_type, exc_val, exc_tb):
print(f"斷開與資料庫的連接: {self.db_name}...")
# 這裡應該是實際的資料庫關閉邏輯
self.connection = None
if exc_type:
print(f"在連接期間發生錯誤: {exc_val}")
return False # 返回 False 表示如果發生異常,就讓異常繼續傳播
# 使用自定義的上下文管理器
with DatabaseConnection("my_rental_db") as db:
print(f"操作資料庫: {db}")
# raise ValueError("模擬一個錯誤") # 嘗試取消這行,看錯誤處理
print("資料庫連接操作完成。")
範例 3: 使用 @contextmanager
(更簡潔)
from contextlib import contextmanager
@contextmanager
def managed_resource(name):
print(f"獲取資源: {name}")
try:
yield name # 這裡返回資源,並在此處執行 with 塊中的程式碼
finally:
print(f"釋放資源: {name}")
with managed_resource("租車預訂鎖") as lock:
print(f"在鎖 {lock} 的保護下執行預訂操作...")
# 這裡可以放置需要加鎖的關鍵代碼
print("預訂操作完成。")
優勢:
- 資源管理: 確保資源(文件、網路連接、鎖)被正確獲取和釋放。
- 代碼清晰: 減少錯誤處理代碼,使資源管理邏輯集中化。
這些進階概念是 Python 語言的核心,理解並熟練運用它們將極大地提升你的程式設計能力,使你能夠開發更健壯、更高效、更易於維護的應用程式,這對於未來在 AI 領域的開發也是至關重要的。
沒有留言:
張貼留言