国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python裝飾器(decorator)定義與用法詳解

2020-01-04 15:53:56
字體:
來源:轉載
供稿:網友

本文實例講述了Python裝飾器(decorator)定義與用法。分享給大家供大家參考,具體如下:

什么是裝飾器(decorator)

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

裝飾器

最簡單的函數,返回兩個數的和

def calc_add(a, b): return a + bcalc_add(1, 2)

但是現在又有新的需求,計算求和操作耗時,很簡單,求和前獲取一下時間,求和后再獲取一次,求差即可

import datetimedef calc_add(a, b): start_time = datetime.datetime.now() result = a + b end_tiem = datetime.datetime.now() print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs" return resultcalc_add(1, 2)

現在呢,函數calc_diff(a, b),計算a-b,也想計算減法操作的時間差,很好辦,把那段代碼復制過去.但是假如我們現在想編的是一個數學函數庫,各種函數都想計算其執行耗時,總不能一個一個復制代碼,想個更好的辦法.

我們知道,在Python中函數也是被視為對象的,可以作為參數傳遞,那么假如把計算耗時的獨立為一個單獨的函數calc_spend_time(),然后把需要計算耗時的函數例如calc_add的引用傳遞給它,在calc_spend_time中調用calc_add,這樣所有的需要計算耗時的函數都不用修改自己的代碼了.

def calc_spend_time(func, *args, **kargs): start_time = datetime.datetime.now() result = func(*args, **kargs) end_tiem = datetime.datetime.now() print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs"def calc_add(a, b): return a + bcalc_spend_time(calc_add, 1, 1)# calc_spend_time(calc_add, a=1, b=2)

看起來也不錯,負責計算的函數不用更改,只需調用的時候作為參數傳給計算時間差的函數.但就是這,調用的時候形式變了,不再是clac(1, 2),而是calc_spend_time(clac_add, 1, 2),萬一calc_add大規模被調用,那么還得一處一處找,然后修改過來,還是很麻煩.如果想不修改代碼,就得使clac()calc_spend_time(clac)效果一樣,那么可以在calc_spend_time()里把傳入的clac包裝一下,然后返回包裝后的新的函數,再把返回的包裝好的函數賦給clac,那么calc()的效果就和上例calc_spend_time(calc())效果一樣.

import datetimedef calc_spend_time(func): def new_func(a, b):  start_time = datetime.datetime.now()  result = func(a, b)  end_tiem = datetime.datetime.now()  print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs" return new_funcdef calc_add(a, b): return a + bcalc_add = calc_spend_time(calc_add)calc_add(1, 2)

語法糖

上面的例子就是裝飾器的概念,包裝函數的函數.事實上上面的例子還可以更精簡

import datetimedef calc_spend_time(func): def new_func(a, b):  start_time = datetime.datetime.now()  result = func(a, b)  end_tiem = datetime.datetime.now()  print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs" return new_func@calc_spend_timedef calc_add(a, b): return a + bcalc_add(1, 2)

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

無參數的函數裝飾器

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

注:

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

帶參數的函數裝飾器

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

import datetimedef calc_spend_time(author): def first_deco(func):  def new_func(*args, **kargs):   start_time = datetime.datetime.now()   result = func(*args, **kargs)   end_tiem = datetime.datetime.now()   print author, "result:", result, "used:", (end_tiem - start_time).microseconds, "μs"  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 - bcalc_add(a=1, b=2)calc_diff(1, 2)

Python內置裝飾器

Python內置的裝飾器有三個:staticmethodclassmethodproperty

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

class Human(object): """docstring for Human""" def __init__(self):  super(Human, self).__init__() @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 helloI say hi

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

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

輸出同上例

property:把方法變成屬性

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

希望本文所述對大家Python程序設計有所幫助。


注:相關教程知識閱讀請移步到python教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 本溪市| 娄烦县| 康定县| 府谷县| 临猗县| 隆尧县| 冕宁县| 澜沧| 玛曲县| 二手房| 沈阳市| 依兰县| 襄城县| 晋中市| 上虞市| 汤阴县| 柏乡县| 辽中县| 临沭县| 清镇市| 香港 | 时尚| 霞浦县| 墨竹工卡县| 山东省| 寻甸| 大英县| 化隆| 荥经县| 犍为县| 新龙县| 安达市| 民乐县| 襄汾县| 昭苏县| 绥化市| 崇信县| 年辖:市辖区| 德钦县| 保山市| 灵武市|