python3裝飾器

python裝飾器

預備知識

首先咱們要知道在python,一切皆對象,函數也是一個對象 python

>>> def test():
...     return "Hello World"

有本身的id值,有type,有本身的值app

>>> id(test)
140155005410568
>>> type(test)
<class 'function'>
>>> test
<function test at 0x7f78614f9d08>

甚至能夠賦值給其餘變量函數

>>> test1 = test
>>> test1()
'Hello World'

哪怕是當作參數傳遞給別的函數,也能夠當作函數的返回值網站

>>> def foo(func):
...     print(func)
...     return func
... 
>>> test2 = foo(test)
<function test at 0x7f78614f9d08>
>>> test2()
'Hello World'

裝飾器定義

裝飾器本質其實就是一個函數, 可讓其它函數不改動源代碼的狀況下增長其餘新功能, 好比網站常常須要的權限校驗等場景code


最初的函數

def add(x, y):
    print(x+y)

add(1,2)

如今咱們有一個新需求, 計算代碼執行時間orm

import time

def add(x, y):
    start_time = time.time
    print(x+y)
    stop_time = time.time
    print("{func} spend {time} ".format(func = "add", time = stop_time-start_time))

add(1,2)

咱們固然能夠這麼寫, 可是一來修改了源代碼可能會形成一些未知的錯誤, 二來若是咱們有一百個函數, 這樣寫也不現實, 這就是咱們裝飾器出場的時候了.對象

建立一個裝飾器

import time 

def timmer(func):
    """
    :param func: 被裝飾的函數
    :return: 一個計算函數運行時間的函數
    """
    def wrapper(*args, **kwargs):
        """
        :param args:收集被裝飾函數的參數
        :param kwargs:收集被裝飾函數的關鍵字參數
        :return:
        """
        start_time = time.time()
        # 讓進程睡一秒
        time.sleep(1)
        # 調用被裝飾的函數
        result = func(*args, **kwargs)
        stop_time = time.time()
        print("{func} spend {time} ".format(func = "add", time = stop_time-start_time))
        return result
    return wrapper

使用裝飾器

def add(x, y):
    print(x,y)
# 由於timmer返回的是wrapper函數對象,因此執行add()至關於執行wrapper()
add = timmer(add)
add(1,2)

若是以爲仍是麻煩那就經過一個語法糖@符號來使用裝飾器

@timmer
def add(x, y):
    print(x,y)

add(1,2)

這就是最基本的裝飾器, 在不修改源代碼的前提下爲函數添加一個新功能, 調用時只須要在原函數上方添加一個 @deco_name , 在這裏是@timmer進程


帶參數的裝飾器

python還容許咱們給裝飾器帶上函數io

import time

def timmer(flag):
    """
    :param flag: 接收裝飾器的參數
    :return:
    """
    def outer_wrapper(func):
        """
        :param func: 接收被裝飾的函數
        :return:
        """
        # 接收被裝飾函數的參數
        def wrapper(*args, **kwargs):
            """

            :param args: 收集被裝飾函數的參數
            :param kwargs: 收集被裝飾函數的關鍵字參數
            :return:
            """
            if flag == "true":
                start_time = time.time()
                # 調用被裝飾的函數
                result = func(*args, **kwargs)
                # 讓進程睡一秒
                time.sleep(1)
                stop_time = time.time()
                print("{func} spend {time} ".format(func="add", time=stop_time - start_time))
                return result
            else:
                print("Unexpected ending")
        return wrapper
    return outer_wrapper

經過一個語法糖@符號來使用裝飾器

所謂的語法糖即是你不使用也能夠完成任務,可是使用它可讓你的代碼更簡潔function

@timmer(flag="false")
def add(x, y):
    print(x, y)

add(1,2)

被多個裝飾器裝飾

當函數被多個裝飾器裝飾時,從裏向外裝飾

@a
@b
@c
def func():
    pass

至關於

func = a(b(c(func)))
相關文章
相關標籤/搜索