裝飾器

  • 裝飾器的應(yīng)用場景:

    • 面向?qū)ο?OOP)

    • 登錄認(rèn)證

    • flask路由,全部都是有參裝飾器

裝飾器:在不修改源代碼及調(diào)用方式的前提下,額外添加新的功能,符合開放封閉封閉原則就是裝飾器:

  1. 對額外新增的功能是開放的

  2. 對源代碼及調(diào)用方式是封閉的

# 3個人寫的代碼,分別計算各自代碼運行的時間,但是又不能改變代源代碼
import time
?
# 創(chuàng)建一個裝飾器函數(shù)
 def run_time(f):
 '''
 計算時間的函數(shù)
 :param f: 接收要計算時間的函數(shù)
 '''
     def inner();
         start_time = time.time()
         f()
         time.sleep(2)
         end_time = time.time()
         print(f'{f}運行時間:{end_time-start_time}')
     return inner 
?

def func():
 print('這是jones寫的代碼')

def foo():
 print('這是tins寫的代碼')

def fl():
 print('這是zhong寫的代碼')


a = func  # a就是func函數(shù)
func = run_time  # func就是run_time
func(a) # 本質(zhì)上還是run_time(func),但是不滿足調(diào)用方式方式封閉

func()

標(biāo)準(zhǔn)版裝飾器實現(xiàn)原理:

  • 類似于現(xiàn)實中的租房,裝飾器就是中介.通過中介來交易
def wrapper(func):
    def inner(*args,**kwargs):
         # 執(zhí)行被裝飾的函數(shù)前
         func(*args,**kwargs) 
         # 執(zhí)行被裝飾的函數(shù)后
     return inner
?
def func1():
 print('這是jones寫的代碼')

func = wrapper(func1)
func()
  • 類似于淘寶的案例
def tb(func):
     def inner(*args,**kwargs):
           res = func(*args,**kwargs)
           return res
     return inner
?
@tb  # 語法糖 store=tb(store)
def store(money):
 '''
 賣家
 '''
     print(f'xx名{money}元賣了一個皮包')
     return 'lv'

?
print(store(100)) # 買家花了100

帶參數(shù)的裝飾器:

# arg只是需要滿足執(zhí)行的條件,才能往下執(zhí)行裝飾器
def f(a):
    def auth(arg): 
        def wrapper(func):
            def inner(*args,**kwargs):
                if arg:
                    print('開始裝飾')
                    ret = func(*args,**kwargs)
                    print('裝飾成功!')
                else:
                    ret = func(*args,**kwargs)
                return ret
            return inner
        return wrapper
    return f

auth = f(1)
@auth(1)  # 本質(zhì)上就是foo = auth(True)(foo)
def func(a):
    print(a)
    
func(10)

=無論有多少個嵌套函數(shù),都是一樣的,一層一層解開即可=


image-20200919180422289.png

多個裝飾器裝飾一個函數(shù)

def wrapper(func):
    def inner(*args, **kwargs):
        print('is wrapper start')
        ret = func(*args, **kwargs)
        print('finish wrapper')
        return ret

    return inner


def wrapper1(func):
    def inner1(*args, **kwargs):
        print('is wrapper start')
        ret1 = func(*args, **kwargs)
        print('finish wrapper')
        return ret1

    return inner1

# 拆語法糖執(zhí)行順序
@wrapper        # 1.foo = wrapper(foo)
@wrapper1       # 2.foo = wrapper1(foo)
def foo():
    print('is foo')
 
    
foo()  # 3.foo() = inner1() 
        # 4.foo() = inner()
-----------------------------------------
is wrapper start
is wrapper1 start
is foo
finish wrapper1
finish wrapper
  • 多個裝飾器的執(zhí)行順序是
  1. 程序是從上往下執(zhí)行的,所以先解開的語法糖是wrapper,再解開wrapper2,所以輸出的是is wrapper start,在輸出is wrapper1 start
  2. 然而此時的foo() == inner1(),因為只調(diào)用了一次foo()所以,往下執(zhí)行的是finish wrapper1
  3. 到這wrapper1已經(jīng)執(zhí)行完了,而wrapper還沒有執(zhí)行完,所以接著執(zhí)行finish wrapper整個程序執(zhí)行結(jié)束
    image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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