python函數裝飾器
聲明:博主并沒有系統學習過python語言,在實際項目中遇到關于python不懂的語法,這里僅作為個人學習積累筆記
1.1 python函數相關基礎
深入了解python函數裝飾器移步:Python 函數裝飾器
下面的筆記來源于上述鏈接
python中將函數賦值給變量,并不會執行該函數,函數只有加括號才會被調用
def hi():print("")greet = hi # 函數hi不會被調用,只是將函數賦值給了變量
hi() # 函數會被執行
# 若要通過greet來執行hi函數
greet() # 變量變為了函數
函數中嵌套函數,所有的嵌套函數會被一同執行,并且嵌套函數不能被外界單獨訪問
def hi():def greet():……def welcome():……
hi() #調用函數hi()則greet() welcome()會被一同調用
函數中嵌套函數時,從中返回某個特定嵌套函數
def hi(name="func1"):def greet():……def welcome():……if name == "func1":return greetelse:return welcome
a = hi() # 將hi()函數返回的函數賦值給a
print(a()) #調用a函數,即返回的greet函數
函數作為另一個函數的參數傳入
def hi():……def func2(func1): print(func1())
func2(hi) #將函數hi作為參數傳入函數func2,在func2中執行hi函數
1.2 裝飾器的核心作用
Python函數裝飾器是一種高階函數,其核心作用是在不修改原函數代碼的情況下動態擴展函數功能。這種特性使得裝飾器在代碼復用、功能解耦、邏輯增強等方面具有獨特優勢。
簡單了解裝飾器的其中一個作用:
動態功能擴展:為函數添加額外行為
裝飾器的核心能力是在不改變原函數內部代碼的情況下,為其包裹新的功能邏輯。
例如實現函數調用日志記錄:
def log_decorator(func):def wrapper(*args, ?**kwargs):print(f"[LOG] 開始執行 {func.__name__},參數:{args}")result = func(*args, ?**kwargs) # 調用原函數print(f"[LOG] {func.__name__} 執行完成,結果:{result}")return resultreturn wrapper@log_decorator # 等價于 add = log_decorator(add) 將原函數add作為參數傳遞給log_decorator函數
def add(a, b): # add變量被重新綁定為log_decorator(add)的返回值(即內部函數wrapper)return a + badd(3, 5)
# 輸出:
# [LOG] 開始執行 add,參數:(3, 5)
# [LOG] add 執行完成,結果:8
裝飾器的應用階段(代碼加載時)當Python解釋器加載@log_decorator語法時,會立即執行裝飾器函數log_decorator:
函數調用階段(運行時)當執行add(3, 5)時,實際調用的是被裝飾后的wrapper函數
執行順序
調用 add(3,5)
│
├─> 進入 wrapper(3,5)
│ ├─> 執行 [LOG] 開始執行 add,參數:(3,5)
│ ├─> 調用 func(3,5) → 原始add函數
│ │ └─> 計算 3+5=8
│ └─> 執行 [LOG] add 執行完成,結果:8
│
└─> 返回最終結果8
1.3 python函數裝飾器的實際應用:請求限流
控制API調用頻率:防止服務被惡意高頻調用
def rate_limit(max_calls, period):def decorator(func):calls = []def wrapper(*args):now = time.time()# 清除超時記錄calls[:] = [t for t in calls if now - t < period]if len(calls) >= max_calls:raise Exception("請求過于頻繁")calls.append(now)return func(*args)return wrapperreturn decorator@rate_limit(5, 60) # 每分鐘最多5次, rate_limit返回decorator, decorator接收api_request函數
def api_request(): # api_request = rate_limit(api_request)# 調用外部API
代碼結構拆解,該代碼通過裝飾器工廠實現了一個滑動窗口請求限流器,其核心結構分為三層:
rate_limit(max_calls, period):#裝飾器工廠,接收最大調用次數(max_calls)和時間周期(period秒),返回實際裝飾器decorator
decorator(func):#接收被裝飾函數(如api_request),通過閉包維護調用時間記錄列表calls,返回包裝函數wrapper
wrapper(*args):#實現限流邏輯,包含時間窗口清理、調用計數驗證、異常拋出等核心功能
Python普通函數與閉包函數對比分析
普通函數
(1)獨立定義,無嵌套結構
(2)每次調用均為獨立上下文,無狀態記憶能力
使用普通函數實現計數器
缺點:全局變量不安全,多實例無法并存
count = 0 # 全局變量易被篡改
def increment():global countcount += 1return count
print(increment()) # 1
print(increment()) # 2
閉包函數
(1)嵌套函數結構,內部函數捕獲外部函數變量
(2)通過閉包環境實現狀態持久化
使用閉包函數實現計數器
def create_counter():count = 0def counter():nonlocal countcount += 1return countreturn counter # 每個實例獨立計數
counter1 = create_counter()
counter2 = create_counter()
print(counter1()) # 1(實例1獨立計數)
print(counter2()) # 1(實例2獨立計數)