2020-08-23 Python 裝飾器的理解

1. 為什么要使用裝飾器

比如下面代碼要增加一個(gè)打印時(shí)間的功能,可以通過(guò)對(duì)原函數(shù)進(jìn)行更改,或者再增加一個(gè)函數(shù)完成。
eg:

import time

def f2():
    print("This is f2")

增加一個(gè)打印時(shí)間的功能

a.直接更改原函數(shù)實(shí)現(xiàn)

def f2():
    print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
    print("This is f2")

b.通過(guò)新增加一個(gè)函數(shù)實(shí)現(xiàn)

def print_now_time():
    print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
    f2()

但是如果要是有很多個(gè)函數(shù),那么就要對(duì)很多個(gè)函數(shù)重新改寫(xiě),或者重新定義一個(gè)函數(shù)來(lái)實(shí)現(xiàn)。
那么有沒(méi)有辦法,在保持原有函數(shù)調(diào)用的方法不變,實(shí)現(xiàn)增加一個(gè)打印時(shí)間的功能。那么就引出了裝飾器。

def deco1(func):
    def inner():
        print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
        return func()
    return inner

@deco1
def f2():
    print("This is f2")

f2()

通過(guò)定義裝飾器,在不改變?cè)泻瘮?shù)調(diào)用方法,實(shí)現(xiàn)了新的功能。這個(gè)是我理解的裝飾器的作用。

2.裝飾器執(zhí)行的順序

eg:

import time

def deco1(func):
    print('裝飾器開(kāi)始運(yùn)行了!')
    def inner():
        print('函數(shù)執(zhí)行開(kāi)始了!')
        print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
        return func()
        print('函數(shù)執(zhí)行結(jié)束了!')
    print('裝飾器運(yùn)行結(jié)束了!')
    return inner

@deco1
def f2():
    print("This is f2")

f2()

運(yùn)行結(jié)果:
裝飾器開(kāi)始運(yùn)行了!
裝飾器運(yùn)行結(jié)束了!
函數(shù)執(zhí)行開(kāi)始了!
2020-08-23 10:19:52
This is f2
函數(shù)執(zhí)行結(jié)束了!

通過(guò)以上我們可以知道,裝飾器在程序初始化的時(shí)候,就已經(jīng)開(kāi)始運(yùn)行。但裝飾器里面的函數(shù)是在程序開(kāi)始執(zhí)行的時(shí)候,才開(kāi)始調(diào)用。

那么如果有多個(gè)裝飾器,他們的執(zhí)行順序又是怎么樣的呢?
eg:

import time

def deco1(func):
    print('裝飾器1開(kāi)始運(yùn)行了!')
    def inner():
        print('函數(shù)1執(zhí)行開(kāi)始了!')
        print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
        time.sleep(3)
        return func()
        print('函數(shù)1執(zhí)行結(jié)束了!')
    print('裝飾器1運(yùn)行結(jié)束了!')
    return inner

def deco2(func):
    print('裝飾器2開(kāi)始運(yùn)行了!')
    def inner():
        print('函數(shù)2執(zhí)行開(kāi)始了!')
        print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
        time.sleep(2)
        return func()
        print('函數(shù)2執(zhí)行結(jié)束了!')
    print('裝飾器2運(yùn)行結(jié)束了!')
    return inner

@deco1
@deco2
def f2():
    print("This is f2")

運(yùn)行結(jié)果:
裝飾器2開(kāi)始運(yùn)行了!
裝飾器2運(yùn)行結(jié)束了!
裝飾器1開(kāi)始運(yùn)行了!
裝飾器1運(yùn)行結(jié)束了!
函數(shù)1執(zhí)行開(kāi)始了!
2020-08-23 10:24:58
函數(shù)2執(zhí)行開(kāi)始了!
2020-08-23 10:25:01
This is f2
函數(shù)2執(zhí)行結(jié)束了!
函數(shù)1執(zhí)行結(jié)束了!

從上面我們可以看到,裝飾器是從內(nèi)向外開(kāi)始初始化,裝飾器內(nèi)的程序是從外開(kāi)始先內(nèi)運(yùn)行。

3.以上函數(shù)是未帶參數(shù),如果需要裝飾的函數(shù)帶參數(shù),那么裝飾器又是怎么樣的呢?

eg:

import time

def dec3(func):
    def inner(*args,**kwargs):
        print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
        return func(*args,**kwargs)
    return inner

@dec3
def f3(name):
    print('Good morning',name)

f3('Jon')

輸出結(jié)果:

2020-08-23 10:34:14
Good morning Jon

4. 函數(shù)可以帶參數(shù)去執(zhí)行了,那么裝飾器是否可以帶上參數(shù)呢?

eg:

import time

def judeg(times):
    def dec4(func):
        def inner(*args,**kwargs):
            hour=time.localtime().tm_hour - times
            if hour >=0:
                print('現(xiàn)在距離{times}點(diǎn)已過(guò){hour}小時(shí)'.format(times=times,hour=hour))
            else:
                print('現(xiàn)在距離{times}點(diǎn)還有{hour}小時(shí)'.format(times=times,hour=-hour))
            return func(*args,**kwargs)
        return inner
    return dec4

@judeg(12)
def f4(name):
    print("Hello",name)

f4('Mike')

運(yùn)行結(jié)果:

現(xiàn)在距離12點(diǎn)還有1小時(shí)
Hello Mike

5. 類(lèi)裝飾器

eg:

class Foo:
    def __init__(self,func):
        self._func = func

    def __call__(self):
        print("裝飾器開(kāi)始運(yùn)行!")
        self._func()
        print("裝飾器運(yùn)行結(jié)束!")
@Foo
def f1():
    print('Hello')


f1()

參考1
參考2

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容