亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python函數式編程裝飾器的示例分析

發布時間:2022-03-03 13:38:12 來源:億速云 閱讀:157 作者:小新 欄目:開發技術

這篇文章給大家分享的是有關Python函數式編程裝飾器的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

一、裝飾器的本質:

裝飾器(decorator)本質是函數閉包(function closure)的語法糖(Syntactic sugar)

函數閉包(function closure):

函數閉包是函數式語言(函數是一等公民,可作為變量使用)中的術語。函數閉包:一個函數,其參數和返回值都是函數,用于增強函數功能面向切面編程(AOP)

import time
# 控制臺打印100以內的奇數:
def print_odd():
    for i in range(100):
        if i % 2 == 1:
            print(i)
# 函數閉包:用于增強函數func:給函數func增加統計時間的功能:
def count_time_wrapper(func):
    def improved_func():
        start_time = time.time()
        func()
        end_time = time.time()
        print(f"It takes {end_time - start_time} S to find all the odds in range !!!")
    return improved_func
if __name__ == '__main__':
    # 調用count_time_wrapper增強函數
    print_odd = count_time_wrapper(print_odd)
    print_odd()

閉包本質上是一個函數,閉包函數的傳入參數和返回值都是函數,閉包函數得到返回值函數是對傳入函數增強后的結果。

日志裝飾器:

def log_wrapper(func):
    """
    閉包,用于增強函數func: 給func增加日志功能
    """
    def improved_func():
        start_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))  # 起始時間
        func()  # 執行函數
        end_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))  # 結束時間
        print("Logging: func:{} runs from {} to {}".format(func.__name__, start_time, end_time))
    return improved_func

二、裝飾器使用方法:

通過裝飾器進行函數增強,只是一種語法糖,本質上跟上個程序(使用函數閉包)完全一致。

Python函數式編程裝飾器的示例分析

import time
# 函數閉包:用于增強函數func:給函數func增加統計時間的功能:
def count_time_wrapper(func):
    def improved_func():
        start_time = time.time()
        func()
        end_time = time.time()
        print(f"It takes {end_time - start_time} S to find all the odds in range !!!")
    return improved_func
# 控制臺打印100以內的奇數:
@count_time_wrapper  # 添加裝飾器
def print_odd():
    for i in range(100):
        if i % 2 == 1:
            print(i)
if __name__ == '__main__':
    # 使用  @裝飾器(增強函數名) 給當前函數添加裝飾器,等價于執行了下面這條語句:
    # print_odd = count_time_wrapper(print_odd)
    print_odd()

裝飾器在第一次調用被裝飾函數時進行增強,只增強一次,下次調用仍然是調用增強后的函數,不會重復執行增強!

保留函數參數和返回值的函數閉包:

  • 之前所寫的函數閉包,在增強主要功能函數時,沒有保留原主要功能函數的參數列表和返回值。

  • 一個保留參數列表和返回值的函數閉包寫法:

def general_wrapper(func):
    def improved_func(*args, **kwargs):
        # 增強函數功能:
        ret = func(*args, **kwargs)
        # 增強函數功能:
        return ret
    return improved_func

優化裝飾器(參數傳遞、設置返回值): 

import time
# 函數閉包:用于增強函數func:給函數func增加統計時間的功能:
def count_time_wrapper(func):
    # 增強函數:
    def improved_func(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"It takes {end_time - start_time} S to find all the odds in range !!!")
        # 原函數返回值
        return result
    return improved_func
# 計算0-lim奇數之和:
@count_time_wrapper
def count_odds(lim):
    cnt = 0
    for i in range(lim):
        if i % 2 == 1:
            cnt = cnt + i
    return cnt
if __name__ == '__main__':
    result = count_odds(10000000)
    print(f"計算結果為{result}!")

三、多個裝飾器的執行順序:

# 裝飾器1:
def wrapper1(func1):
    print("set func1")  # 在wrapper1裝飾函數時輸出
    def improved_func1(*args, **kwargs):
        print("call func1")  # 在wrapper1裝飾過的函數被調用時輸出
        func1(*args, **kwargs)
        return None
    return improved_func1
# 裝飾器2:
def wrapper2(func2):
    print("set func2")  # 在wrapper2裝飾函數時輸出
    def improved_func2(*args, **kwargs):
        print("call func1")  # 在wrapper2裝飾過的函數被調用時輸出
        func2(*args, **kwargs)
        return None
    return improved_func2
@wrapper1
@wrapper2
def original_func():
    pass
if __name__ == '__main__':
    original_func()
    print("------------")
    original_func()

Python函數式編程裝飾器的示例分析

這里得到的執行結果是,wrapper2裝飾器先執行,原因是因為:程序從上往下執行,當運行到:

@wrapper1
@wrapper2
def original_func():
    pass

這段代碼時,使用函數閉包的方式解析為:

original_func = wrapper1(wrapper2(original_func))

所以先進行wrapper2裝飾,然后再對被wrapper2裝飾完成的增強函數再由wrapper1進行裝飾,返回最終的增強函數。

Python函數式編程裝飾器的示例分析

四、創建帶參數的裝飾器:

裝飾器允許傳入參數,一個攜帶了參數的裝飾器將有三層函數,如下所示:

import functools
def log_with_param(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            print('call %s():' % func.__name__)
            print('args = {}'.format(*args))
            print('log_param = {}'.format(text))
            return func(*args, **kwargs)
        return wrapper
    return decorator
@log_with_param("param!!!")
def test_with_param(p):
    print(test_with_param.__name__)
if __name__ == '__main__':
    test_with_param("test")

將其 @語法 去除,恢復函數調用的形式:

# 傳入裝飾器的參數,并接收返回的decorator函數
decorator = log_with_param("param!!!")
# 傳入test_with_param函數
wrapper = decorator(test_with_param)
# 調用裝飾器函數
wrapper("I'm a param")

感謝各位的閱讀!關于“Python函數式編程裝飾器的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

双江| 乌拉特中旗| 长汀县| 津南区| 禄劝| 德格县| 清丰县| 太湖县| 景德镇市| 盐津县| 鄂州市| 宜君县| 遵义县| 石屏县| 太谷县| 乐安县| 西昌市| 陆丰市| 隆子县| 雷山县| 井研县| 毕节市| 聊城市| 柘城县| 南汇区| 侯马市| 乳源| 台北市| 云阳县| 郑州市| 东辽县| 潼关县| 无棣县| 峨边| 潜江市| 历史| 汉寿县| 竹北市| 柳江县| 嘉义市| 广德县|