17 裝飾器的使用[python基礎(chǔ)]

裝飾器

1. 

用于拓展原來函數(shù)功能的一種函數(shù)
2.
返回函數(shù)的函數(shù)
3.
在不用更改原函數(shù)的代碼前提下給函數(shù)增加新的功能

//如果沒有裝飾器
def hello():
    print('hello world')

def test():
    print('test...')

def hello_wrapper():
    //新的函數(shù),包裹原來的hello
    print('進(jìn)入函數(shù)hello')
    hello()
    print('結(jié)束執(zhí)行hello')

def test_wrapper():
    print('進(jìn)入函數(shù)hello')
    test()
    print('結(jié)束執(zhí)行hello')

if __name__ == '__main__':
    //要實(shí)現(xiàn)這樣的功能,就要建立多個(gè)wrapper(),而且有變化需要修改多個(gè)地方,不好維護(hù)
    hello_wrapper()
    test_wrapper()

//實(shí)現(xiàn)裝飾器,用裝飾器實(shí)現(xiàn)
def log(func)
    //記錄函數(shù)執(zhí)行的日志
    def wrapper():
        print('start...')
        func()
        print('end...')

def log_in(func)
    //記錄函數(shù)執(zhí)行的日志
    def wrapper():
        print('開始...')
        func()
        print('結(jié)束...')

@log
def hello():
    //簡單功能模擬
    print('hello world')

@log
@log_in   //裝飾器可以使用多個(gè),按順序嵌套執(zhí)行
def test()
    print('test...')

if __name__ == '__main__':
    hello()
    test()

//帶參數(shù)的裝飾器
def log(name = None):  //允許默認(rèn)值,可以不傳參
    
    def decorator(fun):
        def wrapper():
            print('{0} start...'.format(name))
            fun()
            print('{0} end...'.format(name))
        return wrapper
    return decorator                     //返回函數(shù)不要帶括號

@log('hello')  //也可以不傳參 @log()
def hello():
    print('hello world')

@log('test')
def test():
    print('test...')

if __name__ == '__main__':
    hello()
    test()

//如果帶參數(shù)的裝飾器,同時(shí)自定義的函數(shù)本身也帶參數(shù)和返回值,如何傳遞使用

def log(name = None):  //允許默認(rèn)值,可以不傳參
    
    def decorator(func):  
        def wrapper(*args, **kwargs):       //這里就要傳入add(a, b)的參數(shù).用兩個(gè)魔法參數(shù),一個(gè)元組,一個(gè)字典
            print('{0} start...'.format(name))
            rest = func(*args, **kwargs)                //這里就要傳入add(a, b)的參數(shù),用一個(gè)臨時(shí)變量保存返回值
            print('{0} end...'.format(name))
            return rest   //為了執(zhí)行上一句打印,在這里返回臨時(shí)變量值
        return wrapper
    return decorator                     //返回函數(shù)不要帶括號

@log('hello')  //也可以不傳參 @log()
def hello():
    print('hello world')

@log('test')
def test():
    print('test...')

def  add(a, b, *args, **kwargs):    //有參數(shù),有返回值,如何使用,帶兩個(gè)魔法參數(shù),傳更多的變量
    return a + b

if __name__ == '__main__':
    //hello()
    //test()

    rest = add(5, 6, k = 5, v = 6)

///裝飾器之wraps

def log(name = None):  //允許默認(rèn)值,可以不傳參
    
    def decorator(func):  
        @wraps(func)    //j加上這個(gè)裝飾器,就可以解決注釋__doc__和名字__name__等被改變的問題
        def wrapper(*args, **kwargs):       //這里就要傳入add(a, b)的參數(shù).用兩個(gè)魔法參數(shù),一個(gè)元組,一個(gè)字典
            //注釋:裝飾器內(nèi)部的函數(shù)
            print('{0} start...'.format(name))
            rest = func(*args, **kwargs)                //這里就要傳入add(a, b)的參數(shù),用一個(gè)臨時(shí)變量保存返回值
            print('{0} end...'.format(name))
            return rest   //為了執(zhí)行上一句打印,在這里返回臨時(shí)變量值
             //原始hello()的注釋名字是在這附近發(fā)生了改變  ,如果不用@wraps需要在下面進(jìn)行手動更改
        //wrapper.__doc__ = func.__doc__
        //wrapper.__name__ = func.__name__
        //但是每個(gè)都這么操縱很麻煩,所以pyton提供了一個(gè)@wraps用來使用,放在裝飾器內(nèi)部函數(shù)上

                
        return wrapper
    return decorator                     //返回函數(shù)不要帶括號

@log('hello')  //也可以不傳參 @log()
def hello():
    //注釋:簡單功能模擬
    print('hello world')

  if __name__ == '__main__':
    print('doc: {0}'.format(hello.__doc__))
    print('doc: {0}'.format(hello.__name__))  //結(jié)果注釋和名字都不是hello()的,而是變成了裝飾器內(nèi)部的函數(shù)wrapper()的注釋和名字,這時(shí)候就需要用到@wraps
    hello()

///裝飾器注意事項(xiàng):
1,用@wraps 還原原始函數(shù)的注釋\名字等信息
2,用魔法傳參 *args, **kwargs 解決自己的函數(shù)傳參問題
3,自己的函數(shù)有返回值的,把函數(shù)返回值用臨時(shí)變量保存起來,執(zhí)行完裝飾器內(nèi)邏輯后,再return
4,也可以用于類

///類的裝飾器

def f(self): //可以在這里擴(kuò)展類的方法
print('{0}: 我愛吃東西'.format(self.name))
print('000000') //

def eat(cls):
//cls.eat = lambda self: print('{0}: 我愛吃東西'.format(self.name)) //簡單的用lambda,更豐富可以用下面方法
cls.eat = f
return cls

@eat
class Cat(object):
//貓類
def init(self, name)
self.name = name

if name == 'main':
cat = Cat('小黑')
cat.eat()

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

相關(guān)閱讀更多精彩內(nèi)容

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