裝飾器 Decorator

裝飾器 Decorator

Posted by 劉啟仲 on Thursday, December 24, 2020

裝飾器 Decorator

加工修飾加上一些我們要的功能

print_fun_name(func) 會把傳入的 function 再利用一個我們命為 wrapper( )的內部function做加工,然後在用 return wrapper 吐出修飾過的 function wrapper,就完成「修飾」的任務

def print_fun_name(func):
	def wrapper():
    	print("runing: ", func.__name__)
      func()
  return wrapper

def Say():
	print("Hi~")

if __name__ == "__main__"
	Say = print_fun_name(Say)
  Say()
  # runing: Say
  # Hi~

當有很多function都需要做相同的事情或執行相同的程式碼,就可以用裝飾器來做。

例如:計算時間就很適合使用裝飾器

def print_fun_name(func):
	def wrapper():
    	print("runing: ", func.__name__)
      func()
  return wrapper

def fun_Timer(func):
	def wrapper():
    	import time
			start = time.time()
      func()
      end = time.time()
			print('elapsed', end - start, 'seconds')
  return wrapper

def Say():
	print("Hi~")

if __name__ == "__main__"
	Say = print_fun_name(Say)
  Say = fun_Timer(Say)
  Say()
  # runing: Say
  # elapsed 0.00192748472394 seconds

可以直接用@做加裝。syntax candy(語法糖、語法糖衣)。

裝飾器的多層會有順序性,會先合併最靠近的裝飾器,所以會先裝上@fun_Timer在裝上@print_fun_name,因為在第一個@fun_Timer加工後function被包裝為wrapper,所以後面再加裝@print_fun_name後,印出的名稱會為"runing: wrapper"。

def print_fun_name(func):
	def wrapper():
    	print("runing: ", func.__name__)
      func()
  return wrapper

def fun_Timer(func):
	def wrapper():
    	import time
			start = time.time()
      func()
      end = time.time()
			print('elapsed', end - start, 'seconds')
  return wrapper

@print_fun_name
@fun_Timer
def Say():
	print("Hi~")

if __name__ == "__main__"
  Say()
  # runing: wrapper
  # elapsed 0.00192748472394 seconds

Decorator 的優點:

  • 靈活度高
  • 易讀性高
  • 協助封裝效果好
  • 程式碼重複率低/簡潔度高