python基礎之裝飾器

裝飾器的本質是一個閉合函數,該閉合函數的自由變量是一個函數,可以使代碼的重要性與擴展性大大加強。

通過@後添加裝飾器函數

能夠接收任何參數的通用參數裝飾器

# 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"))

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章