python函數式編程3(裝飾器的深刻理解)

1、什麼是裝飾器

  • 一、python中裝飾器能夠理解爲AOP編程,有點相似Spring中的註解,在不改變原函數或類的基礎上,對函數或類添加額外(本身需求補充)的功能。
  • 二、裝飾器本質上是一個函數,該函數用來處理其餘函數,它可讓其餘函數在不須要修改代碼的前提下增長額外的功能,裝飾器的返回值也是一個函數對象。
  • 三、有了裝飾器,咱們就能夠抽離出大量與函數功能自己無關的雷同代碼並繼續重用。
  • 四、好比咱們要給每個函數新增一個打印logger日誌,咱們就可使用裝飾器,在不修改原函數的前提下,新增功能又能作到代碼的解耦。

2、裝飾器的幾個原則及學習裝飾器必要的知識儲備

3、裝飾器的演變過程

  • 一、定義一個裝飾器(計算函數執行時間)編程

    import time
    
    def timer(func):
    	def wrapper():
          start_time = time.time()
          res = func()
          end_time = time.time()
          print('程序運行時間:{0}'.format(end_time - start_time))
          return res
      return wrapper
    複製代碼
  • 二、定義一個要執行的函數app

    def foo():
        time.sleep(3)
        print('主函數')
    複製代碼
  • 三、根據上面幾個原則,咱們來調用函數foo函數

    if __name__ == "__main__":
    		# 1.timer函數中傳遞函數foo進去
    		# 2.爲了避免改變函數的調用方式,將timer函數的返回值(函數)賦值給變量foo
        foo = timer(foo) # 前面foo是新定義的變量,timer中的foo是上面定義的foo函數
        foo() # timer是一個高階函數,返回的是一個函數
    複製代碼
  • 四、解答上面的代碼學習

    • 1.定義的裝飾器是一個高階函數,被裝飾的函數做爲參數傳遞進去
    • 2.在知足裝飾的原則下,咱們把高階函數執行後從新賦值給foo函數
    • 3.foo()函數的執行就沒改變原有函數的調用方式
  • 五、使用裝飾器**@**spa

上面第四點中2和3步驟在python中直接使用**@**語法糖來處理日誌

@timer
def bar():
    time.sleep(2)
    print('主函數')
  
if __name__ == "__main__":
    bar()
複製代碼

4、裝飾器中傳遞參數

import time

def timer(func):
  def wrapper(*args, **kwargs):
      start_time = time.time()
      res = func(*args, **kwargs)
      end_time = time.time()
      print('執行時間:{0}'.format(end_time - start_time))
      return res

  return wrapper

@timer
def foo(name, gender):
  time.sleep(3)
  print(name)
  print(gender)

if __name__ == "__main__":
  foo('張三', gender='男')
複製代碼

5、使用類來做裝飾器

建立一個數據庫操的log的裝飾器code

  • 一、具體實現代碼orm

    from functools import wraps
    from datetime import datetime
    
    # 建立一個類的裝飾器
    class Log(object):
        def __init__(self, logfile='log.log'):
            self.logfile = logfile
    
        def __call__(self, func):
     @wraps(func)
            def wrapper(*args, **kwargs):
                self.writelog(*args, **kwargs)
                return func(*args, **kwargs)
    
            return wrapper
    
        # 把日誌寫到本地
        def writelog(self, *args, **kwargs):
            time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            log_str = time + ' 操做人:{0[0]} 進行了【{0[1]}】操做'.format(args)
            # 寫入本地文件中
            with open(self.logfile, 'a', encoding='utf8') as file:
                file.write(log_str + '\n')
    
    @Log()
    def printLog(name, type):
        print('姓名:{0},type:{1}'.format(name, type))
    
    if __name__ == "__main__":
        printLog('張三', '查詢')
        printLog('李四', '新增')
    複製代碼
  • 二、執行結果(本地文件夾下多一個文件)

    2018-06-24 10:47:40 操做人:張三 進行了【查詢】操做
    2018-06-24 10:47:40 操做人:李四 進行了【新增】操做
    複製代碼
更多原著博文請參考
相關文章
相關標籤/搜索