裝飾器的本質是一個閉合函數,該閉合函數的自由變量是一個函數,可以使代碼的重要性與擴展性大大加強。
通過@後添加裝飾器函數
能夠接收任何參數的通用參數裝飾器
# def checkParams(fn):
# """只接受字符串的裝飾器"""
# def wrapper(strname):
# if isinstance(strname,(str)):#判斷是否是字符串類型
# return fn(strname)#如果是則調用fn(strname),返回計算結果
# print("Variable strname is not a string type")
# return
# return wrapper#將裝飾後的函數返回
def checkParams(fn):
"""能夠接收任何參數的通用參數裝飾器"""
def wrapper(*arg,**kwargs):#使用字典和元組的解包參數來做形參
if isinstance(arg[0],(str)):#判斷第一個參數是否是字符串
return fn(*arg,**kwargs)
return
return wrapper
@checkParams
def wrapperfun(strname):
def recoder(age):
print("姓名:",strname,"年紀:",age)
return recoder
fun=wrapperfun("Anna")#wrapperfun帶有參數檢查的閉合函數
fun(37)#爲age賦值
fun=wrapperfun(546)#當輸入參數不合法時,
fun(37)#沒有輸出顯示
可接收參數的通用裝飾器
def isadmin(userid):
"""可接收參數的通用裝飾器"""
def checkPArams(fn):
def wrapper(*arg,**kwargs):#定義一個檢查參數的函數
if userid!='admin':#
print("Operation is prothibited as you are not admin!")
return
if isinstance(arg[0],(str)):#判斷是否是字符串
return fn(*arg,**kwargs)
print("variable strname is not a string type")
return
return wrapper#裝飾後的函數返回
return checkPArams
@isadmin(userid="admin")
def wrapperfun(strname):
def recoder(age):
print("姓名:",strname,"年紀:",age)
return recoder
@isadmin(userid="user")
def wrapperfun2(strname):
def recoder(age):
print("姓名:",strname,"年紀:",age)
return recoder
fun=wrapperfun("Ana")
fun(20)
fun1=wrapperfun2("as")
# fun1(37)
fun2=wrapperfun2(123)
除了通過@加函數導入裝飾器,還可以通過
wrapperfun=isadmin(userid="admin")(wrapperfun)
實現裝飾器導入。
組合裝飾器
將不同的裝飾器使用@符號一行一行的疊堆起來
@isadmin(userid="admin")
@checkParams
裝飾器返回函數的名稱修復
當函數被裝飾完後,對函數的名字屬性再賦一次值,將函數的名稱恢復過來
# import functools
def isadmin(userid):
def checkParams(fn):
# @functools.wraps(fn)#保證修飾後的函數與原函數的名稱一致
def wrapper(*arg,**kwargs):
if userid!="admin":
print("Operation is prohibited as you are not admin!")
return
if isinstance(arg[0],(str)):
return fn(*arg,**kwargs)
print("variable strname is not a string type")
return
wrapper.__name__=fn.__name__#將函數名稱屬性恢復,或者通過#@functools.wraps(fn)實現
return wrapper
return checkParams
@isadmin(userid="admin")
def wrapperfun3(strname):
def recoder(age):
print("姓名:",strname,"年紀:",age)
return recoder
wrapperfun3=isadmin(userid="admin")(wrapperfun3)
fun=wrapperfun3("Anana")
fun(22)
通過裝飾器實現網站爬取中的重試功能
import requests
def retry(attempt): #定義裝飾器函數
def decorator(func):
def wrapper(*args,**kw):
att=0
while att<attempt: #按照計數器att的條件來執行循環語句
print(att)
try: #使用try except捕獲異常
return func(*args,**kw) #運行請求
except Exception as e:
att+=1 #調整計數器
return wrapper
return decorator
@retry(attempt=3)
def get_response(url):
r=requests.get(url)
return r
URL="http://www.baidu.com"
r=get_response(URL)
print(r)
if (r!=None):
print(r.content.decode("utf-8"))