Python中的decorator是一種對python語法的轉換寫法,使用decorator可以更方便的對函式作修改,也可以提高程式的可讀性。但是decorator只是一種語法糖,使用decorator並不會對語法產生改變,只是讓程式寫法可以更加的簡潔,並且讓開發者可以更方便的使用。
下面開始來說明一下,如何使用decorator來實作在函式的修改:
假設我們寫了一個執行sql的函式:
| 12
 
 | def select_execute(sql):    return 'execute select sql query!'
 
 | 
如果我們想要對這個執行sql的函式,用一個debug模式來包起來,並在debug模式印出執行的sql與執行的時間,這時可以透過closure來處理函式
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | def debug_query(func):    def debug_execute(sql):
 exec_msg = func(sql)
 exec_time = datetime.now()
 debug_msg = """
 Execute: {sql}
 Result: {exec_msg}
 Execute Time: {exec_time}"""
 return debug_msg.format(**locals())
 return debug_execute
 
 >>> sql = 'SELECT * FROM TABLE'
 >>> select_execute(sql)
 execute select sql query!
 
 >>> func = debug_query(select_execute)
 >>> func(sql)
 Execute: SELECT * FROM TABLE
 Result: execute select sql query!
 Execute Time: 2017-05-20 16:09:08.953792
 
 | 
從上面的範例可以看到,先將執行sql的函式傳入外部函式,並在內部函式捕捉後,加上debug要印的部份進行改寫,這樣就可以將執行sql的函式包裝成debug模式。下面是使用decorator的寫法
| 12
 3
 4
 5
 6
 7
 8
 
 | @debug_querydef select_execute(sql):
 return 'execute select sql query!'
 
 >>> select_execute(sql)
 Execute: SELECT * FROM TABLE
 Result: execute select sql query!
 Execute Time: 2017-05-20 16:09:08.953792
 
 | 
只要透過@和改寫的函式名稱,就可以簡化函式傳遞的語法,讓程式碼可以更加簡潔並達到相同效果
decorator也可以支援帶參數,如果今天要簡單的多印出一行debug宣告,並指定是哪一種query type作說明,可以透過多加上一層outter函式來傳入參數
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 
 | def debug_describe(query_type):    def debug_query(func):
 def debug_execute(sql):
 exec_msg = func(sql)
 exec_time = datetime.now()
 descirbe = 'It is {} debug mode'.format(query_type)
 debug_msg = """
 {descirbe}
 Execute: {sql}
 Result: {exec_msg}
 Execute Time: {exec_time}"""
 return debug_msg.format(**locals())
 return debug_execute
 return debug_query
 
 >>> func = debug_describe('select')(select_execute)
 >>> func(sql)
 It is select debug mode
 Execute: SELECT * FROM TABLEResult: execute select sql query!
 Execute Time: 2017-05-20 16:09:08.962798
 
 @debug_describe('select')
 def select_execute(sql):
 return 'execute select sql query!'
 
 >>> select_execute(sql)
 Execute: SELECT * FROM TABLE
 Result: execute select sql query!
 Execute Time: 2017-05-20 16:09:08.962798
 
 | 
參考資料:
PythonDecorators
Understanding Decorators in Python
Python Decorator 四種寫法範例 Code