python --裝飾器

裝飾器 

裝飾器:
 把一個函數當作參數,返回一個替代版的函數
 本質上就是一個返回函數的函數

 “在不改變原函數的基礎上,給函數增加功能”

def decorator(func):
    def wrapper(*args,**kwargs):         # 設置形參,設置關鍵字參數**kwargs
        print(time.time())
        func(*args,**kwargs)             # 執行所所裝飾的函數
    return wrapper                      
 
@decorator
def f1 (func_name):
    print('This is a function '+func_name)
@decorator
def f2 (func_name1,func_name2):
    print('This is a function '+func_name1)
    print('This is a function '+func_name2)
@decorator
def f3(func_name1,func_name2,**kwargs):
    print('This is a function '+func_name1)
    print('This is a function '+func_name2)
    print(kwargs)
# 函數中有關鍵字參數
f1('test')
f2('test1','test2')
f3('test1','test2',a=1,b=2,c='westos')

裝飾器使用練習

裝飾器實現一個函數計時器

def decorator(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)    # 對函數運行結果進行處理,ruturn的結果無法直接顯示出來,需通過print打印或者傳給一個變量
        end_time = time.time()
        print('running time is: %.6f'  %(end_time - start_time))
        return res
    return wrapper
 
@decorator
def f1_list(n):
    return [2 * i for i in range(n)]
 
@decorator
def f1_map(n):
    return list(map(lambda x:x*2,range(n)))
 
print(f1_list(10000))    # 對比結果,list執行速度快
print(f1_map(10000))

創建裝飾器,要求如下:
1. 創建add_log裝飾器,被裝飾的函數打印日誌信息
2. 日誌格式爲: [字符串時間]函數名: XXX,運行時間:XXX,運行返回值結果:XXX

注意:添加幫助文檔後如果在執行某函數時使用幫助文檔的參數,則會顯示該函數的幫助文檔

'''
time.ctime() 標準時間的生成
func.__name__ 獲取func函數名
'''
import time
import functools
 
def add_log(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        end_time = time.time()
        print('[%s] 函數名: %s,運行時間: %.6f,運行返回值結果: %d' %(time.ctime(),func.__name__,end_time-start_time,res))
        return res
    return wrapper
 
@add_log
def add(x,y):
    time.sleep(1)
    return x+y
add(1,2)

 isinstance(數字,數據類型)  # 判斷數字是否是該類型的,是則返回true,否則返回false
編寫裝飾器required_types,條件如下:
1). 當裝飾器爲@required_types(int,float)確保函數接收的每一個
2). 當裝飾器爲@required_types(list)確保函數接收到的每一個參數都是list類型
3). 當裝飾器爲@required_types(str,int)確保函數接收到的每一個
4). 如果參數不滿足條件,打印TypeError:參數類型必須爲XXX類型 

import functools
def required_types(*kind):        # 接收裝飾器的參數
    def required(fun):
        @functools.wraps(fun)
        def wrapper(*args,**kwargs):
            for i in args:
                if not isinstance(i,kind):
                    print('TypeError,參數必須爲%s,%s類型' %kind)
                    exit()
            else:
                res = fun(*args,**kwargs)
                return res
        return wrapper
    return required
 
@required_types(int,float)
def add (a,b):
    return a+b
print(add('westos',2))

多個裝飾器 

在有多個裝飾器時,會按順序從上到下執行

def decorator_a(fun):
    def inner_a(*args,**kwargs):
        print('This is inner_a')
        return fun(*args,**kwargs)
    return inner_a
def decorator_b(fun):
    def inner_b(*args,**kwargs):
        print('This is inner_b')
        return fun(*args,**kwargs)
    return inner_b
 
@decorator_b
@decorator_a
def f(x):
    print('This is f')
f(1)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章