1. 程式人生 > >Python基礎-----裝飾器

Python基礎-----裝飾器

字符串 test 中間 name 接收 %d lis str ping

#!/usr/bin/env python
# -*- coding:utf-8 -*-

一、裝飾器定義
器即函數;裝飾即修飾,意指為其他函數添加新功能;
裝飾器定義:本質就是函數,功能是為其他函數添加新功能
二、裝飾器的原則
1.不修改被裝飾函數的源代碼(開放封閉原則)
2.為被裝飾函數添加新功能後,不修改被修飾函數的調用方式
三、高階函數
滿足如下條件之一就可稱之為高階函數
1.函數接收的參數是一個函數名
2.函數的返回值是一個函數名
高階函數總結
1.函數接收的參數是一個函數名
  作用:在不修改函數源代碼的前提下,為函數添加新功能,
  不足:會改變函數的調用方式
2.函數的返回值是一個函數名
  作用:不修改函數的調用方式
  不足:不能添加新功能
四、閉包
閉包:在一個作用域裏放入定義變量(或嵌套函數),相當於打了一個包
想要給內部傳入參數,用閉包的話只需要在最外部傳入即可
def father(name):
def son():
def grandson():
print(‘from %s‘%name)
grandson()
son()

father(‘林海峰‘)
五、裝飾器框架實現
‘‘‘
import time
def timmer(func): #func = test
def wrapper():
start_time = time.time()
func() #執行test函數
stop_time = time.time()
print(‘運行時間%s‘%(stop_time - start_time))
return wrapper

def test():
time.sleep(3)
print(‘函數運行完畢‘)

test = timmer(test) #返回的是wrapper的函數地址
test() #執行wrapper函數,內部再運行test函數
‘‘‘
上面代碼符合裝飾器的基本原則,但是調用test函數之前進行了賦值操作
六、裝飾器語法糖
@裝飾函數 (將該句代碼放置於修飾函數前即可)
就上例來講,@timmer 就相當於 test = timmer(test)
‘‘‘
import time
def timmer(func): #func = test
def wrapper():
start_time = time.time()
func() #執行test函數
stop_time = time.time()
print(‘運行時間%s‘%(stop_time - start_time))
return wrapper

@timmer #等同於test = timmer(test)
def test():
time.sleep(3)
print(‘函數運行完畢‘)

test()
‘‘‘
# 七、加上返回值
‘‘‘
import time
def timmer(func): #func = test
def wrapper():
start_time = time.time()
res = func() #執行test函數
stop_time = time.time()
print(‘運行時間%s‘%(stop_time - start_time))
return res
return wrapper

@timmer #等同於test = timmer(test)
def test():
time.sleep(3)
print(‘函數運行完畢‘)
return ‘這是test的返回值‘
a = test() #實際執行wrapper函數
print(a)
‘‘‘
八、加上參數
‘‘‘import time
def timmer(func): #func = test
def wrapper(name,age):
start_time = time.time()
res = func(name,age) #執行test函數,參數來自wrapper接收的參數
stop_time = time.time()
print(‘運行時間%s‘%(stop_time - start_time))
return res
return wrapper

@timmer #等同於test = timmer(test)
def test(name,age):
time.sleep(3)
print(‘我叫%s,年齡%d‘%(name,age))
return ‘這是test的返回值‘
a = test(‘alex‘,18) #實際執行wrapper函數‘‘‘
但是參數是固定的,不適用於所有函數,則改變如下:
‘‘‘import time
def timmer(func): #func = test
def wrapper(*args,**kwargs): #可以用* **來傳入多參數
start_time = time.time()
res = func(*args,**kwargs) #執行test函數,參數來自wrapper接收的參數
stop_time = time.time()
print(‘運行時間%s‘%(stop_time - start_time))
return res
return wrapper

@timmer #等同於test = timmer(test)
def test(name,age):
time.sleep(3)
print(‘我叫%s,年齡%d‘%(name,age))
return ‘這是test的返回值‘

@timmer
def test1(name,age,gender):
time.sleep(3)
print(‘我叫%s,年齡%d,性別%s‘%(name,age,gender))
return ‘這是test的返回值‘
a = test(‘alex‘,18) #實際執行wrapper函數
b = test1(‘tony‘,22,‘male‘) #該處將‘tony‘,22,‘male‘參數放入*args == *(‘tony‘,22,‘male‘)(一一對應,相當於解壓)‘‘‘
九、列表解壓
如要獲取列表的第一個和最後一個值,不用索引來取
‘‘‘l = [10,2,3,4,5,7,5,4,2,32]
first_num,*other_num,last_num = l # *+變量名 表示中間的所有元素
print(first_num,last_num)
print(*other_num)‘‘‘

如需互換兩個變量的值
‘‘‘a = 1
b = 2
a,b = b,a
print(a,b)‘‘‘

十、實例(驗證功能裝飾器)
user_list = [
{‘name‘:‘a‘,‘password‘:‘123‘},
{‘name‘:‘b‘,‘password‘:‘123‘},
{‘name‘:‘c‘,‘password‘:‘123‘},
{‘name‘:‘d‘,‘password‘:‘123‘}
] #所有用戶信息列表(值為字符串類型)

current_user = {‘username‘:None,‘login‘:False} #記錄用戶當前登錄狀態

def auth_func(func):
def wrapper(*args,**kwargs):
if current_user[‘username‘] and current_user[‘login‘]: #如果已經登錄,則無需登陸
res = func(*args,**kwargs)
return res
username = input(‘用戶名:‘).strip() #上面if不成立,則登錄
password = input(‘密碼:‘).strip()
for user_dic in user_list: #for遍歷的是用戶列表的中用戶信息字典
if username == user_dic[‘name‘] and password == user_dic[‘password‘]: #登錄驗證
current_user[‘username‘] = username #登錄成功,更改用戶狀態
current_user[‘login‘] = True
res = func(*args,**kwargs)
return res
else: #該處else沒放在if下是因為,要遍歷所有的用戶列表才能判斷是否真的有錯
print(‘用戶名或密碼錯誤,請重新登錄!‘)
return wrapper

@auth_func
def home(name):
print(‘歡迎 %s 來到主頁‘%name)

@auth_func
def shopping_car(name):
print(‘%s 的購物車裏有:學習用品,生活用品!‘%name)

home(‘Jerry‘)
print(current_user)
shopping_car(‘Jerry‘)

Python基礎-----裝飾器