第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Flask 中的裝飾器

總體來說,Python 的語(yǔ)法比較簡(jiǎn)單,是一門易學(xué)的編程語(yǔ)言。但是,Python 的裝飾器語(yǔ)法是一個(gè)例外,裝飾器是 Python 語(yǔ)言的高級(jí)語(yǔ)法,牽涉到高階函數(shù)等內(nèi)容,對(duì)初學(xué)者來說較難理解。

看到這里你可能會(huì)問:咱們這門課程不是學(xué)習(xí) Flask 框架嗎?怎么又扯到裝飾器上面去了?
這是因?yàn)檠b飾器語(yǔ)法在 Flask 框架中得到了廣泛的應(yīng)用,想要學(xué)好 Flask 框架不理解裝飾器的概念是不行滴。

因此這個(gè)小節(jié)我們就專門來討論下裝飾器的用途、定義和原理,為大家深入理解 Flask 框架原理打下一個(gè)重要基礎(chǔ)。

1. 高階函數(shù)

1.1 把函數(shù)當(dāng)作對(duì)象

本節(jié)從底層原理講解了如何實(shí)現(xiàn)裝飾器,學(xué)員需要深入理解 Python 中 “函數(shù)是第一類對(duì)象” 的概念,可以參考詞條 “Python 的 lambda 表達(dá)式”。在這個(gè)詞條中對(duì)這一概念具有比較系統(tǒng)的講解。

在 Python 中,函數(shù)是第一類對(duì)象的意思是指函數(shù)作為一個(gè)對(duì)象,與其它對(duì)象具有相同的地位。具體來說,一個(gè)數(shù)值對(duì)象可以:

  • 被賦值給變量;
  • 作為參數(shù)傳遞給函數(shù);
  • 作為返回值。

因?yàn)楹瘮?shù)和數(shù)值具有相同的地位,所以函數(shù)也可以:

  • 被賦值給變量;
  • 作為參數(shù)傳遞給函數(shù);
  • 作為返回值。

1.2 把函數(shù)作為輸入?yún)?shù)

上面說到函數(shù)也可以被作為參數(shù)傳遞給另外一個(gè)函數(shù),下面我們就用一個(gè)例子來演示一下:

def double(item):
    return item + item

def triple(item):
    return item + item + item

定義函數(shù) double,返回輸入值的 2 倍;定義函數(shù) triple,返回輸入值的 3 倍。

def map(func, input):
    output = []
    for item in input:
        new_item = func(item)
        output.append(new_item)
    return output

定義函數(shù) map,接受兩個(gè)參數(shù):func 和 input。參數(shù) func 是一個(gè)函數(shù),參數(shù) input 是一個(gè)列表, 對(duì)輸入列表 input 中的每個(gè)元素依次進(jìn)行處理,返回一個(gè)新列表 output。

在第 3 行,遍歷輸入列表 input 中的每個(gè)元素,調(diào)用 func (item) 生成一個(gè)新的元素 new_item,將 new_item 加入到 output 中,最后返回 output。

print(map(double, [1, 2, 3]))
print(map(triple, [1, 2, 3]))

對(duì)序列 [1, 2, 3] 中的每個(gè)元素使用函數(shù) double 進(jìn)行處理;對(duì)序列 [1, 2, 3] 中的每個(gè)元素使用函數(shù) triple 進(jìn)行處理。

運(yùn)行程序,輸出如下:

[2, 4, 6]
[3, 6, 9]

序列 [1, 2, 3] 中的每個(gè)元素乘以 2 后,得到序列 [2, 4, 6];序列 [1, 2, 3] 中的每個(gè)元素乘以 3 后,得到序列 [3, 6, 9]。

1.3 把函數(shù)作為返回值

在下面的例子中,將函數(shù)作為返回值:

def func():
    print('Inside func')

def return_func():   
    print('Inside return_func')
    return func

在第 1 行,定義函數(shù) func;在第 3 行,定義函數(shù) return_func,函數(shù) return_func 返回一個(gè)函數(shù)類型的對(duì)象,將函數(shù) func 作為值返回。

var = return_func() 
var()

調(diào)用 return_func (),將函數(shù)的返回值保存到變量 var。變量 var 的類型是函數(shù),因此可以進(jìn)行函數(shù)調(diào)用。

程序的輸出結(jié)果如下:

Inside return_func
Inside func

2. 裝飾器與高階函數(shù)

在上面的兩個(gè)例子中把函數(shù)作為參數(shù)或者吧函數(shù)作為返回值的函數(shù)在 Python 中被統(tǒng)稱為是高階函數(shù),而我們本節(jié)課的重點(diǎn)裝飾器本質(zhì)上其實(shí)就是一個(gè)特殊的高階函數(shù),那么它特殊在哪里呢?

通過上面的兩個(gè)例子我們可以了解到高階函數(shù)有兩個(gè)特性:

  • 輸入?yún)?shù)是函數(shù);
  • 輸出返回值是函數(shù)。

而裝飾器(decorate)則是兩種特性都具備,也就是說裝飾器函數(shù)的參數(shù)是一個(gè)函數(shù),返回值也是一個(gè)函數(shù)。

圖片描述

函數(shù) decorate 對(duì)函數(shù) input 的功能進(jìn)行擴(kuò)充,生成并返回一個(gè)新的函數(shù) output,新的函數(shù) output 的功能基于函數(shù) input。裝飾器的中裝飾的含義是指:對(duì)函數(shù) input 的功能進(jìn)行裝飾 (擴(kuò)充功能),得到一個(gè)新函數(shù) output

3. 裝飾器的用途

既然我們已經(jīng)知道了裝飾器本質(zhì)上就是一個(gè)函數(shù),只不過比較特殊而已,下面我們就一起來看下裝飾器可以用在什么地方:

3.1 需求

使用 Python 編寫了 3 種排序算法:

  • quick_sort,快速排序;
  • bubble_sort,冒泡排序;
  • select_sort,選擇排序。

現(xiàn)在需要對(duì)這 3 個(gè)算法進(jìn)行性能評(píng)測(cè),記錄并打印每個(gè)排序算法的執(zhí)行時(shí)間。

import time

def quick_sort():
    time.sleep(1)

def bubble_sort():
    time.sleep(2)

def select_sort():
    time.sleep(3)

引入 time 模塊,使用 time.sleep () 模擬函數(shù)的執(zhí)行時(shí)間;使用 time.sleep (1) 模擬 quick_sort 的執(zhí)行時(shí)間為 1 秒;使用 time.sleep (2) 模擬 bubble_sort 的執(zhí)行時(shí)間為 2 秒;使用 time.sleep (3) 模擬 select_sort 的執(zhí)行時(shí)間為 3 秒。

3.2 不使用裝飾器

對(duì)于這個(gè)需求,我們先不使用裝飾器,僅使用 Python 的基礎(chǔ)語(yǔ)法完成任務(wù),如下所示:

import time

def quick_sort():
    start_time = time.time()
    time.sleep(1)
    end_time = time.time()
    print('%.2f seconds' % (end_time - start_time))

引入 time 模塊,需要使用 sleep 方法;在函數(shù)的頭部,記錄開始時(shí)間 start_time; 在函數(shù)的尾部,記錄結(jié)束時(shí)間 end_time;打印開始時(shí)間和結(jié)束時(shí)間的差,即函數(shù)的執(zhí)行時(shí)間。

def bubble_sort():
    start_time = time.time()
    time.sleep(2)
    end_time = time.time()
    print('%.2f seconds' % (end_time - start_time))

def select_sort():
    start_time = time.time()
    time.sleep(3)
    end_time = time.time()
    print('%.2f seconds' % (end_time - start_time))

使用同樣的方法,對(duì) bubble_sort 和 select_sort 進(jìn)行修改。

quick_sort()
bubble_sort()
select_sort()

依次調(diào)用 quick_sort、bubble_sort、select_sort,打印它們各自的運(yùn)行時(shí)間,程序輸出如下:

1.00 seconds
2.00 seconds
3.00 seconds

3.3 使用裝飾器

在上一個(gè)小節(jié)中,我們沒有使用裝飾器同樣完成了需求,但是這樣做存在一個(gè)明顯的問題:

  • quick_sort、bubble_sort、select_sort 存在代碼重復(fù);
  • 在函數(shù)頭部記錄開始時(shí)間、在函數(shù)尾部記錄結(jié)束時(shí)間,邏輯是完全相同的。

而通過使用裝飾器,可以消除代碼重復(fù),代碼如下:

import time

def quick_sort():
    time.sleep(1)

def bubble_sort():
    time.sleep(2)

def select_sort():
    time.sleep(3)

在上一節(jié)的例子中,需要對(duì) quick_sort、bubble_sort 和 select_sort 進(jìn)行修改。在本節(jié)的例子中,不對(duì) quick_sort、bubble_sort 和 select_sort 進(jìn)行任何修改。

def decorate(input_sort):
    def output_sort():
        start_time = time.time()
        input_sort()
        end_time = time.time()
        print('%.2f seconds' % (end_time - start_time))

    return output_sort

裝飾器 decorate 是一個(gè)高階函數(shù),輸入?yún)?shù) input_sort 是一個(gè)排序函數(shù),返回值是 output_sort 一個(gè)功能增強(qiáng)的排序函數(shù)。

在第 3 行,在 output_sort 函數(shù)的頭部,記錄開始時(shí)間,調(diào)用原排序函數(shù) input_sort;在第 5 行,在 output_sort 函數(shù)的尾部,記錄結(jié)束時(shí)間。

quick_sort = decorate(quick_sort)
bubble_sort = decorate(bubble_sort)
select_sort = decorate(select_sort)

使用 decorate (quick_sort),生成一個(gè)功能增強(qiáng)的 quick_sort,并替換原有的 quick_sort;使用 decorate (bubble_sort),生成一個(gè)功能增強(qiáng)的 bubble_sort,并替換原有的 bubble_sort;使用 decorate (select_sort),生成一個(gè)功能增強(qiáng)的 select_sort,并替換原有的 select_sort。

quick_sort()
bubble_sort()
select_sort()

依次調(diào)用 quick_sort、bubble_sort、select_sort,打印它們各自的運(yùn)行時(shí)間,程序輸出如下:

1.00 seconds
2.00 seconds
3.00 seconds

4. Python 的裝飾器語(yǔ)法

4.1 裝飾器語(yǔ)法

對(duì)裝飾器這樣的高階函數(shù)的應(yīng)用,Python 提供了特殊的裝飾器語(yǔ)法,用法如下:

def decorate(input_function):
    def output_function():
        pass
    return output_function

@decorate
def input_function():
    pass

首先定義裝飾器函數(shù) decorate,然后使用 @decorate 裝飾需要增強(qiáng)功能的函數(shù) input_function。以上使用裝飾器語(yǔ)法 @decorate 的代碼會(huì)被翻譯如下:

def decorate(input_function):
    def output_function():
        pass
    return output_function

def input_function():
    pass

input_function = decorate(input_function)

decorate 函數(shù)接受輸入?yún)?shù) input_function,返回一個(gè)功能增強(qiáng)的函數(shù) output_function。 用功能增強(qiáng)的新函數(shù) output_function 替換原有的舊函數(shù) input_function。

4.2 使用裝飾器語(yǔ)法

在本小節(jié),使用 Python 的裝飾器語(yǔ)法實(shí)現(xiàn)對(duì)三種排序算法的性能評(píng)測(cè):

import time

def decorate(input_sort):
    def output_sort():
        start_time = time.time()
        input_sort()
        end_time = time.time()
        print('%.2f seconds' % (end_time - start_time))

    return output_sort

裝飾器 decorate 是一個(gè)高階函數(shù),輸入?yún)?shù) input_sort 是一個(gè)排序函數(shù),返回值是 output_sort 一個(gè)功能增強(qiáng)的排序函數(shù)。

在 output_sort 函數(shù)的頭部,記錄開始時(shí)間,調(diào)用原排序函數(shù) input_sort,在 output_sort 函數(shù)的尾部,記錄結(jié)束時(shí)間。

@decorate
def quick_sort():
    time.sleep(1)

@decorate
def bubble_sort():
    time.sleep(2)

@decorate
def select_sort():
    time.sleep(3)

使用裝飾器 decorate 裝飾 quick_sort,得到一個(gè)功能增強(qiáng)的 quick_sort;使用裝飾器 decorate 裝飾 bubble_sort,得到一個(gè)功能增強(qiáng)的 bubble_sort;使用裝飾器 decorate 裝飾 select_sort,得到一個(gè)功能增強(qiáng)的 select_sort。

quick_sort()
bubble_sort()
select_sort()

依次調(diào)用 quick_sort、bubble_sort、select_sort,打印它們各自的運(yùn)行時(shí)間,程序輸出如下:

1.00 seconds
2.00 seconds
3.00 seconds

5. 小結(jié)

本小節(jié)講解了裝飾器的原理以及裝飾器的功能,裝飾器主要用于在原有函數(shù)的基礎(chǔ)上增強(qiáng)功能,使用思維導(dǎo)圖概括如下:

圖片描述