1. 程式人生 > >python裝飾器三種裝飾模式的簡單理解

python裝飾器三種裝飾模式的簡單理解

學設計模式中有個裝飾模式,用java實現起來不是很難,但是遠遠沒有python簡單,難怪越來越火了!

這裡就簡單討論下python的幾種裝飾模式:

一 無參裝飾器:

# 裝飾器
import time


# 裝飾器,記錄函式執行時間
def decorator01(fun):
    def wapper():
        stime = time.time()
        fun()
        etime = time.time()
        print("fun run time is {TIME}".format(TIME=etime - stime))
    return wapper  # 必須要返回一個函式的記憶體地址


# 使用裝飾器裝飾某個函式,等價於 test01=decorator01(test01),
# 即將test01實際引用變成wapper函式記憶體地址,所以執行test01實際是執行wapper
@decorator01
def test01():
    time.sleep(2)
    print("test01 is running")


test01()  # 不修改程式碼和呼叫方式,實現新增記錄時間功能

  

二 函式帶參裝飾器:

# 裝飾器
import time


# 裝飾器,記錄函式執行時間
def decorator01(fun):
    def wapper(*args, **kwargs): # 使用非固定引數,無論引數是什麼,都可以傳遞進來
        stime = time.time()
        fun(*args, **kwargs)
        etime = time.time()
        print("fun run time is {TIME}".format(TIME=etime - stime))
    return wapper  # 必須要返回一個函式的記憶體地址


# test01() = wapper(), 所以裝飾器加引數是給巢狀函式加引數
@decorator01
def test01(args1):
    time.sleep(2)
    print("引數是 {NAME} ".format(NAME=args1))


test01("侯徵")  # 不修改程式碼和呼叫方式,實現新增記錄時間功能

  

三 裝飾器本身帶引數的裝飾器:

# 裝飾器
import time


# 如果裝飾器有引數,最外層是裝飾器的引數
def decorator01(*args, **kwargs):
    print("裝飾器引數:", *args, **kwargs)
    def out(fun): #第二層才是接受的函式
        def wapper(*args, **kwargs):  # 使用非固定引數,無論引數是什麼,都可以傳遞進來
            stime = time.time()
            fun(*args, **kwargs)
            etime = time.time()
            print("fun run time is {TIME}".format(TIME=etime - stime))

        return wapper  # 必須要返回一個函式的記憶體地址
    return out  # 要返回裝飾函式的記憶體地址


# 裝飾器本身帶引數,此時 decorator01(arg)=out,即相當於 @out裝飾test01,所以 test01=out(fun)=wapper
@decorator01(1)
def test01(args1):
    time.sleep(2)
    print("引數是 {NAME} ".format(NAME=args1))


test01("侯徵")  # 不修改程式碼和呼叫方式,實現新增記錄時間功能

  這種一開始挺難理解的,但是隻要記住一點,@語法糖裝飾器的作用就是 給被裝飾的函式重新賦一個函式的記憶體地址,即裝飾器內部定義的那個

和你直接fun01=decorator(fun),然後 fun01()是一樣的,只是這樣寫不用改變原來呼叫方式

@decorator

def fun():

即就是 fun=decorator(fun)  所以,當裝飾器有引數時,還需要返回一個函式,這個函式才是用來裝飾作用的, decorator(1)=out,  即     fun=out(fun) !!

所以外面再包一層就行了,其實就相當於@decorator(1)[email protected],即 decorator(1)=out ,實際裝飾器時out,只不過decorator(1)返回了一個out 這樣理解就簡單多了 ,無參的@就是起賦值作用