1. 程式人生 > >python-裝飾器

python-裝飾器

驗證 定義 總結 是把 裝飾 ron highlight class 老板

一、介紹

首先我們先來看一個簡單的例子,在基礎平臺中有一個home()和tv()函數,在業務平臺中調用此函數時,給出了響應的打印內容:

基礎平臺:
def home():
    print(‘welcome to home page‘)
def tv(name):
    print(‘welcome to tv page‘)


業務平臺A: 
home()
tv()

業務平臺B:
home()
tv()

    

但是,在後續的需求中規定,在調用此函數時,還需要進行一個用戶驗證

因此程序猿小A的做法是和每個業務部門交涉,每個業務部門自己寫代碼,在調用基礎平臺的時候,先進行驗證:

基礎平臺:
def home():
    print(‘welcome to home page‘)
def tv(name):
    print(‘welcome to tv page‘)


業務平臺A: 
#驗證
home()
tv()

業務平臺B:
#驗證
home()
tv()

小A當天被開除了。。。

後來程序猿小B接手了這份工作,小B的做法是在基礎平臺中加入驗證:

基礎平臺:
def home():
    #驗證
    print(‘welcome to home page‘)
def tv(name):
    #驗證
    print(‘welcome to tv page‘)


業務平臺A: 
home()
tv()

業務平臺B:
home()
tv()

小B的做法相比於小A來說,好了一點,避免了業務平臺的修改,老板為了獎勵小B,因此在一周後把小B開除了。。。

因為小B改動了源代碼

此後,程序猿小C又接受了這個工作。。。

小C說:

寫代碼要滿足以下下兩個原則:

  封閉:已實現的功能代碼不允許被修改

  開放:已實現的功能代碼可以被擴展:

因此,小C打算在此處使用了裝飾器的功能(見下文)

總結:

裝飾器本質上是一個函數,可以在其他函數不做任何代碼變動的情況下,提供一些擴展的功能

二、簡單裝飾器的使用

小C對代碼做出了如下修改(拿tv方法舉例):

def login(func):                   #定義了一個登錄驗證的方法       
    print(‘登錄驗證成功‘)            #假設此處就是一個驗證功能
    return func                    

def tv():
    print(‘welcome to tv page‘ )
tv=login(tv)                       #對tv進行了賦值,此時還沒執行tv方法,只是把該方法放入到了內存中
 
tv()

---執行結果---
登錄驗證成功
welcom to tv page

該代碼是如何實現驗證的呢,步驟如下:

  ①執行login(tv)時,先不執行tv()方法,只是把tv()方法到了內存中,然後執行login()

  ②在login()中進行登錄驗證,之後返回tv()的內存地址,此時tv()還未執行

  ③把tv()的內存地址重新賦值給tv,此時tv變量的值依舊為tv()方法的內容

  ④通過調動tv()執行tv()方法

再經過一些細小的調整,可以寫成如下的形式:

def login(func):                        
    print(‘登錄驗證成功‘)
    return func                    

@login
def tv():
    print(‘welcome to tv page‘ )                   
 
tv()

其中, @XXX 語法,就是一個裝飾器,也稱為“語法糖”

至此,一個簡單的裝飾器雛形已經完成

但是,此處依舊有一個缺點,那就是 即使業務方沒有調用tv(),代碼中也依舊會執行login()中的驗證,為了讓login()中的驗證

不預先執行,因此小C繼續對代碼進行調整

def login(func):
    def inner():
        print(‘登錄驗證成功‘)
        func()
    return inner

@login       
def tv():
    print(‘welcome to tv page‘ )

tv()

此處實現驗證功能的步驟如下:

  ①調用login()方法,返回inner方法的內存地址,此時func的值為tv()內存地址即內容為:

      def tv():
           print(‘welcome to tv page‘ )

  ②把inner方法的內存地址賦值給了變量tv

  ③調用tv(),因為tv的值已經為inner的內存地址,因此調用的是inner()方法

  ④實現inner()中的驗證功能

  ⑤驗證成功後,執行inner()中的func(),打印出‘welcome to tv page’

至此,一個簡單的裝飾器才算真正完成

 

python-裝飾器