1. 程式人生 > >python基礎之裝飾器

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