1. 程式人生 > >Python基礎15_裝飾器

Python基礎15_裝飾器

 一. 裝飾器
    開閉原則: 軟體設計的原則之一, 又稱為開放封閉原則. 
    開放: 對功能擴充套件開放
    封閉: 對修改程式碼封閉
    裝飾器: 在目標函式前或後插入一段新的程式碼, 不改變目標函式的程式碼
    可以給目標函式傳參, 拿到目標函式的返回值
    python裡面的動態代理
    在不破壞目標函式和目標函式呼叫的基礎上給函式新增新的功能
    通用語法:
        def wrapper(fn):                        # fn 是目標函式
            def inner(*args, **kwargs):            # 聚合    給目標函式傳參
                """在目標函式之前進行操作"""
                ret = fn(*args, **kwargs)        # 打散    執行目標函式, 接收目標函式的返回值"xxx"
                """在目標函式之後進行操作"""
                return ret                        # 返回目標函式的返回值"xxx", 保證函式正常結束
            return inner                        # 返回inner的返回值"xxx"
        @wrapper                                # 語法糖 裝飾器中特有 相當於 target_func = wrapper(target_func)
        def target_func()
            pass
            return "xxx"
        # target_func = wrapper(target_func)
        ret = target_func()                        # 執行inner, 並接收inner的返回值"xxx"
        print(ret)                                # 最終列印的是目標函式的返回值"xxx"
二. 帶引數的裝飾器
    
    語法:
    def wrapper_out(形參):                    
        def wrapper(fn):
            def inner(*args, **kwargs):
                """在目標函式之前進行操作"""
                ret = fn(*args, **kwargs)
                """在目標函式之後進行操作"""
                return ret
            return inner
        return wrapper
    @wrapper_out(實參)
    def func():
        pass
    func()
三. 多個裝飾器裝飾同一個函式
    def wrapper1(fn):
        def inner(*args, **kwargs):
            print(111111)
            ret = fn(*args, **kwargs)
            print(222222)
            return ret
        return inner
    def wrapper2(fn):
        def inner(*args, **kwargs):
            print(333333)
            ret = fn(*args, **kwargs)
            print(444444)
            return ret
            return inner
    @wrapper1
    @wrapper2
    def target_func():
        print("我是target_func")
        return "target_func"
    ret = target_func()
    print(ret)
    # 列印結果
        111111
        333333
        我是target_func
        444444
        222222
        target_func
    執行順序: 首先@wrapper2裝飾起來, 然後獲取到一個新函式是wrapper2中的inner, 然後執行@wrapper1, 這個時候, wrapper1裝飾的就是wrapper2中的inner了, 所以執行順序就像: 
    外層裝飾器前 -- 內層裝飾器前 -- 目標 -- 內層裝飾器後 -- 外層裝飾器後 -- 目標函式返回值