標籤:imp 輸出 寫法 sel 效能測試 添加 解決 一個 並且
情景介紹
一天,在你正在努力加班的時候,老闆給交給你了一個任務,就是在這段代碼裡將所有函數開始輸出一個‘hello’最後輸出目前時間,再輸出一個“end”,這段代碼裡包含了大量的函數,你會怎麼做?
def f1(): print(‘proces a‘) def f2(): print(‘proces b‘) def f3(): print(‘proces c‘) def f4(): print(‘proces d‘)......
剛拿到這個任務,我們可能想著這樣做,在每個函數中添加相應的輸出語句,這樣就能完成任務。
import datetimedef f1(): print(‘hello‘) print(‘proces a‘) print(‘datetime.datetime.now()‘) print(‘end‘) def f2(): print(‘hello‘) print(‘proces b‘) print(‘datetime.datetime.now()‘) print(‘end‘)def f3(): print(‘hello‘) print(‘proces c‘) print(‘datetime.datetime.now()‘) print(‘end‘)def f4(): print(‘hello‘) print(‘proces d‘) print(‘datetime.datetime.now()‘) print(‘end‘)......
到我們進行實施的時候我們發現這樣寫,太麻煩,每一個函數最後都要添加一遍,於是,我們就想到了另一個方法,就是寫一個函數,添加在每個函數中。
import datetimedef hel(): print(‘hello‘) print(datetime.datetime.now()) print(‘end‘)def f1(): print(‘hello‘) print(‘proces a‘) hel()def f2(): print(‘hello‘) print(‘proces b‘) hel()def f3(): print(‘hello‘) print(‘proces c‘) hel()def f4(): print(‘hello‘) print(‘proces d‘) hel()......
但是我們發現在開始輸出的hello還是要添加在每個函數中,這樣還是麻煩,為瞭解決這個問題就要講講裝飾器了。
裝飾器介紹
裝飾器本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的傳回值也是一個函數對象。它經常用於有切面需求的情境,比如:插入日誌、效能測試、交易處理、緩衝、許可權校正等情境。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量與函數功能本身無關的雷同代碼並繼續重用。概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能。
簡單裝飾器
就將開始那個問題來使用裝飾器解決一下。
import datetimedef hel(func): def inner(): print(‘hello‘) r = func() print(datetime.datetime.now()) print(‘end‘) return r return inner@heldef f1(): print(‘proces a‘)@heldef f2(): print(‘proces b‘)@heldef f3(): print(‘proces c‘)@heldef f4(): print(‘proces d‘)f1()f2()f3()f4()執行結果:helloproces a2018-06-24 18:03:21.903651endhelloproces b2018-06-24 18:03:21.915651endhelloproces c2018-06-24 18:03:21.915651endhelloproces d2018-06-24 18:03:21.915651end
是不是使用裝飾器相對於之前的寫法簡單。
針對上面的代碼進行解析:
裝飾器符號“@”屬於文法糖,@修飾符必須出現在函數定義前一行,將下面的函數的名作為參數,不允許和函數定義在同一行。
在上面的代碼中,func就是指f1、f2、f3、f4函數,以f1為例,將f1函數作為參數傳入hel函數中,在hel函數中再定義一個inner()函數,在inner函數中,首先執行一個print(‘hello‘),在執行f1函數兵將傳回值賦值給r,接下來輸出時間以及end,最後返回r,inner函數的最後返回inner函數,當我們執行f1函數的時候,就相當於執行了inner函數,並且可以可以拿到f1函數的傳回值。
使用裝飾器傳遞參數
上面使用的裝飾器中,傳入的函數沒有帶參數,當需要修飾的函數帶有參數,我們就在裝飾器中的inner函數添加相應的參數,在inner函數裡面調用func函數的時候,再次傳入。
def hel(func): def inner(name): r = func(name) print(‘bye‘) return r return inner@heldef f1(name): print(‘hello‘) print(name)name = ‘alexsel‘f1(name)輸出結果:helloalexselbye
雖然這樣我們就解決了參數的問題,但是我們這次傳入的參數僅僅是字串,如果是更加複雜的參數怎麼辦,這時候我們可以使用我們之前學習函數時候用到的一些可以接收多種類型的參數,*args,**kwargs,使用這兩個參數之後我們可以接收任何類型的參數。
def hel(func): def inner(*args,**kwargs): r = func(*args,**kwargs) print(‘bye‘) return r return inner@heldef f1(name): print(‘hello‘) print(name)name = ‘alexsel‘f1(name)輸出結果:helloalexselbye
到這裡,簡單的裝飾器就講完了,裝飾器還有更進階的用法,下一篇,裝飾器二會繼續給大家講解裝飾器。
Python學習:10.Python裝飾器講解(一)