1. 程式人生 > 實用技巧 >python:閉包,裝飾器

python:閉包,裝飾器

閉包:

閉包只能存才巢狀函式中
內層函式對外層還輸非全域性變數的引用,就會形成閉包
被引用的非全域性標量也稱作自由變數,這個自由變數會與內層函式產生一個繫結關係
自由變數不會在記憶體中消失

# __code__.co_freevars : 函式的屬性,獲取函式中的自由變數

def wrapper():
    l = []    #這個l 是個自由變數,在函式外部是不能改變 l 的值
    def inner(val):
        l.append(val)
        return sum(l)/len(l)
    return inner
ret = wrapper()
print(ret.__code__.co_freevars) # ('l',),可以當做判斷一個函式是不是閉包 def wrapper(a,b): # 這裡a,b也是自由變數 def inner(): res = a+b return res return inner ret = wrapper(2,3) print(ret.__code__.co_freevars) # ('a', 'b')

裝飾器

裝飾器:在不改變 原函式程式碼 以及 呼叫方式 的前提下,為其增加新的功能
import time
def index():
    time.sleep(
2) print('welcom login') # 模擬登陸 def timmer(f): # 這裡用到了閉包。這裡f是個自用變數,自由變數不受函式外部影響 def inner(): start_time = time.time() f() end_time = time.time() print(f'測試函式的執行效率{end_time-start_time}') return inner index = timmer(index) # 將函式名index作為引數傳遞給timmer(f),實際上傳遞的是index指向的記憶體地址,即 變數f指向了index指向的記憶體地址。然後將返回值inner重新賦值給index,index指向的記憶體地址變成了inner()函式的記憶體地址
index() # 語法糖:@,用來當做裝飾器裝飾函式 ,@timmer()相當於 index = timmer(index) import time def timmer(f): def inner(): start_time = time.time() f() end_time = time.time() print(f'測試函式的執行效率{end_time-start_time}') return inner @timmer # 程式碼執行到這裡的時候,會向下多執行一行 def index(): time.sleep(2) print('welcome login') index() #帶引數有返回值的裝飾器 import time def timmer(f): def inner(*args,**kwargs): st = time.time() ret = f(*args,**kwargs) et = time.time() print(f'login application run time{et - st}') return ret return inner @timmer def login(name): time.sleep(1) print(f'welcome to blog,{name}!!') login('alex') #標準版的裝飾器 def wrapper(f): def inner(*args,**kwargs): ''' 新增額外功能,執行被裝飾函式之前的操作''' ret = f(*args,**kwargs) '''新增額外功能,執行被裝飾函式之後的操作''' return ret return inner # 通過改變一個引數,控制程式碼是否執行 import time def change_start(a): def wrapper(f): def inner(*args,**kwargs): if a: st = time.time() ret = f(*args,**kwargs) et = time.time() ti = et - st return ti else:return 'no run' return inner return wrapper @change_start(False) # 這裡傳遞引數,來控制被裝飾函式是否執行 def login(): time.sleep(1) print(login())