Python3裝飾器詳解

裝飾器

​ 裝飾器本質上是一個函數,該函數用來處理其他函數,它可以讓其他函數在不需要修改代碼的前提下增加額外的功能。裝飾器的返回值也是一個函數對象,它經常用於有切面需求的場景,比如:插入日誌、性能測試、事物處理、緩存、權限校驗等應用場景。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量於函數功能本身無關的雷同代碼繼續重用。概括的講,裝飾器的作用就是爲已經存在的對象添加額外的功能。

​ 一個裝飾器可以用來裝飾多個函數,一個函數也可以被多個裝飾器裝飾 。

​ @符號是裝飾器的語法糖,在定義函數的時候使用,避免再一次賦值操作。

無參裝飾器

​ 它是一個函數,被裝飾函數作爲它的形參,返回值也是一個函數,使用@functionname方式調用。裝飾器是高階函數,裝飾器是對傳入函數的功能的裝飾(增強),不侵入任何代碼。

def logger(fn):
    def wrapper(*args, **kwargs):
        print("args={}, kwargs={}".format(args,kwargs))
        ret = fn(*args, **kwargs)
        print("{}".format(fn.__name__))
        return ret
    return wrapper

@logger             # add = logger(add),返回內層函數的引用
def add(x, y):
    return x + y

print(add(4,5))

帶參裝飾器

​ 帶參裝飾器是在裝飾器外層又加了一層函數

def logger(*paras):
    def _logger(fn):
        def wrapper(*args, **kwargs):
            print("args={}, kwargs={}".format(args,kwargs))
            ret = fn(*args, **kwargs)
            print("paras={}".format(paras))
            print("{}".format(fn.__name__))
            return ret
        return wrapper
    return _logger

@logger(10,20,30)      # add = logger(add),返回內層函數的引用
def add(x, y):
    return x + y

print(add(4,5))

functools模塊

​ 被裝飾後的函數其實已經是另外一個函數了(函數名等函數屬性會發生改變)。爲了不影響,Python的functools包中提供了一個叫wraps的decorator來消除這樣的副作用。寫一個decorator的時候,最好在實現之前加上functools的wraps或者update_wrapper,它能保留原有函數的一些內置屬性,,例如:__name__、 __module__ 、__doc__ 和__dict__等。

import functools

def logger(fn):
    # 方法一
    @functools.wraps(fn)
    def wrapper(*args, **kwargs):
        print("args={}, kwargs={}".format(args,kwargs))
        print(id(fn))
        ret = fn(*args, **kwargs)
        print("{}".format(fn.__name__))
        return ret
    # 方法二
    # functools.update_wrapper(wrapper, fn)
    return wrapper

@logger             # add = logger(add),返回內層函數的引用
def add(x, y):
    return x + y

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