python裝飾器

裝飾器

裝飾器的本質:一個閉包函數

裝飾器的功能:在不修改原函數及其調用方式的情況下對原函數功能進行擴展

import time

def func1():
    print('in func1')

def timer(func):   # 裝飾器函數
    def inner():
        start = time.time()
        func()    # 被裝飾的函數
        print(time.time() - start)
    return inner

func1 = timer(func1)
func1()

#-----------------------------------------------------------
# 語法糖
import time
def timer(func):
    def inner():
        start = time.time()
        func()
        print(time.time() - start)
    return inner

@timer   #==> func1 = timer(func1)
def func1():
    print('in func1')


func1()

裝飾器——帶參數的裝飾器

def timer(func):
    def inner(a):
        start = time.time()
        func(a)
        print(time.time() - start)
    return inner

@timer
def func1(a):
    print(a)

func1(1)

裝飾器——成功hold住所有函數傳參

import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        print(time.time() - start)
        return re
    return inner

@timer   #==> func1 = timer(func1)
def func1(a,b):
    print('in func1')

func1('aaaaaa','bbbbbb')

裝飾器——帶返回值的裝飾器

import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        print(time.time() - start)
        return re
    return inner

@timer   #==> func2 = timer(func2)
def func2(a):
    print('in func2 and get a:%s'%(a))
    return 'fun2 over'

func2('aaaaaa')
print(func2('aaaaaa')

查看函數信息的一些方法

def index():
    '''這是一個主頁信息'''
    print('from index')

print(index.__doc__)    #查看函數註釋的方法
print(index.__name__)   #查看函數名的方法

完美的裝飾器

from functools import wraps

def deco(func):
    @wraps(func) #加在最內層函數正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

@deco
def index():
    '''哈哈哈哈'''
    print('from index')

print(index.__doc__)
print(index.__name__)

裝飾器固定模式

def wrapper(func):
    def inner(*args,**kwargs):
         '''寫函數之前要做的'''
        ret = func(*args,**kwargs)
        '''寫函數之後要做的'''
        return ret
    return inner

@wrapper
def func(*args):
    print(args)
    return 'func over'
    
ret = fuc()
        

開放封閉原則

  • 對擴展是開放的
  • 對修改是封閉的
def warrper(func):
    def inner(*args,**kwargs):
        print('在被裝飾器函數執行之前要做的事')
        ret = func(*args,**kwargs)
        print('在被裝飾器函數執行之後要做的事')
        return ret
    return inner

@warrper  # 等於 holiday = warrper(holiday)
def holiday(day):
    print('全體放假%s天' %day)
    return '好開心'

ret = holiday(3)  # 等於inner(3)
print(ret)

帶參數的裝飾器

def outer(flag):
    def timer(func):
        def inner(*args,**kwargs):
            if flag:
                print('''執行函數之前要做的''')
            re = func(*args,**kwargs)
            if flag:
                print('''執行函數之後要做的''')
            return re
        return inner
    return timer

@outer(False)
def func():
    print(111)

func()
import time
FLAG = True
def timmer_out(flag):
    def timmer(func):
        def inner(*args,**kwargs):
            if flag:
            	start = time.time()
            	ret = func(*args,**kwargs)
            	end = time.time()
           		print(end-start)
            	return ret
            else:
                ret = func(*args,**kwargs)
                return ret        
        return inner
    return timmer

@timmer_out(FLAG)  # 等於@timmer  timmer = timmer_out(FLAG)
def wahaha():
    time.sleep(1)
    print('hahahahaha')
    
wahaha()

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-cTPaA6Ai-1582092534098)(D:\學習筆記\九月\1568686641493.png)]

多個裝飾器裝飾同一個函數

def wrapper1(func): # func --> f
    def inner1():
        print('wrapper1 ,before func')
        func()
        print('wrapper1 ,after func')
    return inner1

def wrapper2(func): # func --> inner1
    def inner2():
        print('wrapper2 ,before func')
        func()
        print('wrapper2 ,after func')
    return inner2

@wrapper2  # f = wrapper2(inner1) = inner2
@wrapper1  # f = wrapper1(f) = inner1
def f():
    print('in f')

f()

# 執行結果

>>> wrapper2 ,before func
>>> wrapper1 ,before func
>>> in f
>>> wrapper1 ,after func
>>> wrapper2 ,after func

發佈了30 篇原創文章 · 獲贊 83 · 訪問量 9129
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章