python_裝飾器入門教程哦

什麼是裝飾器?

簡單來說,可以把裝飾器理解爲一個包裝函數的函數,它一般將傳入的函數或者是類做一定的處理,返回修改之後的對象。
所以我們能夠在不修改原函數的基礎上,在執行原函數前後去執行別的代碼,比較常用的場景有日誌插入,事務處理

我們知道,在python中函數也是被視爲對象的,可以作爲參數傳遞,那麼假如把計算機耗時操作 獨立爲一個單獨的函數,然後只要往裏頭傳入需要計算耗時的函數1 就可以不用往函數1中額外添加計算耗時的語句啦

def calc_spend_time(func,*args,**kargs):
  start_time = datetime.datetime.now()
  result = fun(*args,**kargs)
  end_time = datetime.datetime.now()
  print "result:",result,"used:",(end_time - start_time).microseconds
  
def calc_add(a,b):
  return a + b
  
calc_spend_time(calc_add,1,1)

看起來也不錯,負責計算的函數不用更改代碼,只需調用的時作爲參數傳給計算時間差的函數。
但就是這,調用的時候形式變了,不再是clac(1,2),而是calc_spend_time(clac_add,1,2),萬一calc_add大規模被調用,那麼還得一處一處找,然後修改過來,還是很麻煩???

那麼可以在calc_spend_time()裏把傳入的calc_add()包裝一下,然後返回包裝後的新的函數,再將其賦值給clac_add,那麼calc_add()的效果就和calc_spend_time(calc(),*args,*kwargs)的效果一樣

import datetime
def calc_spend_time(func):
	def new_func(a,b):
	   start_time = datetime.datetime.now()
	   result = fumc(a,b)
	   end_time = datetime.datetime.now()
	   print "result:",result,"used:",(end_time - start_time).microseconds
	return new_func 
	
def calc_add(a,b):
 return a + b
 
calc_add = calc_spend_time(calc_add)
calc_add(1,2) 

語法糖:
上面的列子就是裝飾器的概念,包含函數的函數<函數內部定義一個函數,這個函數需要調用某一個函數>,上面的例子還可以更簡潔

import datetime

def calc_spend_time(func):
	def new_func(a,b):
	   start_time = datetime.datetime.now()
	   result = func(a,b)
	   end_time = datetime.datetime.now()
	   print "result",result,"used:",(end_time - start_time).microseconds,"us"
	return new_func
 
 @calc_spend_time
 def calc_add(a,b):
  return a+b
  
 calc_add(1,2)

分析

@calc_spend_time就是語法糖,它的本質就是:calc_add = calc_spend_time(calc_add)

無參數的函數裝飾器

import datetime
def calc_spend_time(func):
	def new_func(*args,**kargs):
	  start_time = datetime.datetime.now()
	  result = func(*args,**kargs)
	  end_time = datetime.datetime.now()
	  print "result:",result,"used:",(end_time - start_time).microseconds,"us"
	result new_func
	
 @calc_spend_time
 def calc_add(a,b)return a+b
  
 @calc_spend_time
 def calc_diff(a,b):
  return a - b
  
 calc_add(a=1,b=2)
 calc_diff(1,2)

分析

*args:把所有的參數按出現的順序打包成tuple
**kargs:把所有的key=value形式的參數打包成一個dict

帶參數的函數裝飾器

假如我們需要知道函數的一些額外的信息,假如函數作者,可以通過給裝飾器函數增加參數來實現

import datetime
def calc_spend_time(author):
	def first_deco(func):
		def new_func(*args,**kargs):
		   start_time=datetime.datetime.now()
		   result = func(*args,**kargs):
		   end_time = datetime.datetime.now()
		   print author,"result:",result,"used:",(end_time - start_time).microseconds,"us"
		   
		  return new_func
		  
	return first_deco

@calc_spend_time('author_1') 
def calc_add(a,b):
 return a+b

@calc_spend_time('author_2')
def calc_diff(a,b):
 return a-b
 
 # 0. calc_spend_time('author_1')
 # 1. calc_add=first_func(calc_add)
 # 2. cal_add(1,2) =>> new_func(1,2)
 
calc_add(a=1,b=2) 
calc_diff(1,2)

python內置裝飾器

python內置的裝飾器有三個:

staticmethod
classmethod
property

staticmethod
把類中的方法定義爲靜態方法,使用staticmethod裝飾的方法可以使用類或者類的實例對象來調用,不需要傳入self

class Human(object):
 "docstring for Human"
 def __int__(self):
  super(Human,self).__int__()
  
 @staticmethod
 def say(message):
  if not message:
    message = 'hello'
  print 'I say %s'% message
  
 def speak(self,message):
  self.say(message)
  
Human.say(None)
human = Human()
human.speak('hi')

輸出:

I say hello
I say hi

classmmethod
把類中的方法定義爲類的方法,
使用classmethod裝飾的方法可以使用類的或者類的實例對象來調用,
並將該class對象隱式的作爲第一個參數傳入

class Human(object):
 """docstring for Human"""
 def __int__(self):
  super(Human,self).__init__()
  self.message = '111'
  
 def say(message):
  if not message:
    message = "hlleo"
  print "I say %s" %message
  
 @classmethod
 def speak(cls,message):
  if not message:
    message = 'hello'
  cls.say(message)
  
human = Human()
human.speak('hi')
輸出:
I say hello
I say hi

property
把方法變成屬性

class Human(object):
 def __init__(self,value):
  super(Human,self).__init__()
  self.arg = value
  
 @property
 def age(self):
  return self._age
human = Human(20)
print human.age

巨人的肩膀

Python裝飾器的通俗理解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章