本篇文章給大家分享的是有關(guān)Python中如何淺談裝飾器,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
創(chuàng)新互聯(lián)公司是一家專注于成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)與策劃設(shè)計,高臺網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:高臺等地區(qū)。高臺做網(wǎng)站價格咨詢:028-86922220一 裝飾器是什么
裝飾器是一個用于封裝函數(shù)或者類的代碼工具,顯式地將封裝器作用于函數(shù)或者類上,達到程序運行時動態(tài)增加功能的目的。對于函數(shù)運行前處理常見前置條件(常見的web登陸授權(quán)驗證),或者在函數(shù)執(zhí)行之后做善后工作(比如異常處理,記錄log 等等)。
二 如何使用裝飾器
裝飾器本質(zhì)上就是一個可用接受調(diào)用也可以返回調(diào)用的高階函數(shù)。該函數(shù)以被裝飾的函數(shù)為參數(shù)(還可以加上其他值作為參數(shù))。在裝飾器內(nèi)進行裝飾器的邏輯處理,執(zhí)行被裝飾函數(shù),并返回一個裝飾過的函數(shù),聽起來是不是有點繞,Talk is cheap,show me the code .
下面使用函數(shù)now 和函數(shù)add作為例子,
import datetime
def now():
print 'now is ', datetime.datetime.today()
def add(x, y):
ret = x + y
print '{x} + {y} = {retval}'.format(x=x,y=y,retval=ret)
2.1 裝飾器語法
有兩種方式顯示調(diào)用裝飾器的方法。
方法一:func = deco(func)
方法二:Python 2.5之后 為裝飾器引入了特殊的語法 @ --語法糖,在裝飾器名稱前使用@ 符號,添加在被裝飾的函數(shù)定義之前。
@deco
def now():
print 'now is ', datetime.datetime.today()
# 調(diào)用now
now()
小編將從 參數(shù)這個角度來由淺入深介紹裝飾器,函數(shù)有不帶參數(shù)和帶參數(shù)的兩種情況,裝飾器也有帶參數(shù)和不帶參數(shù)的兩種情況,裝飾器對處理帶參數(shù)和不帶參數(shù)的情況也會有鎖不同。
2.2 不帶參數(shù)的情況
我們需要在調(diào)用函數(shù) now 之前和之后加上調(diào)用記錄。
def deco(func):
print 'begin call %s():' % (func.__name__)
func()
print 'end call %s():' % (func.__name__)
return func #裝飾器的參數(shù)是被裝飾的函數(shù)對象,返回原函數(shù)的對象。
yangyiDBA:test yangyi$ python 1.py
begin call now():
now is 2017-05-01 14:40:57.309836
end call now():
now is 2017-05-01 14:40:57.309868
但是從上面的例子看 結(jié)果輸出了兩次now 時間,明顯不符合我們的要求,因為裝飾器必須返回被調(diào)用函數(shù),return func的時候發(fā)生了第二次。后面我們會解決這個問題。
2.3 帶參數(shù)的情況,因為函數(shù)的參數(shù)個數(shù)是不確定的 ,我們需要借助(*args, **kwargs),自動適應(yīng)變參和命名參數(shù)。
#!/usr/bin/env python
# coding:utf-8
import datetime
import functools
def deco(func):
@functools.wraps(func) #
def wrapper(*args, **kw):
print 'begin call %s():' % (func.__name__)
result=func(*args, **kw) # 如果函數(shù)無返回值 ,可以直接使用func(*args, **kw)
print 'end call %s():' % (func.__name__)
return result #這里 result 是為了func 有返回值,
return wrapper
@deco
def add(x, y):
ret = x + y
print '{x} + {y} = {retval}'.format(x=x,y=y,retval=ret)
@deco
def now():
print 'now is ', datetime.datetime.today()
add(2,5)
now()
上面的裝飾器做了如下事情
1 函數(shù)func作為參數(shù)傳給 deco()。
2 functool.wraps 將func 的屬性復(fù)制給 warper。
3 執(zhí)行函數(shù)func前后執(zhí)行某些動作。
4 返回結(jié)果。
5 返回wrapper 函數(shù)對象。
這里特別說明functool.wraps的作用,由于裝飾器導(dǎo)致解釋器認(rèn)為函數(shù)本身發(fā)生了改變,在某些情況下可能會導(dǎo)致一些問題。Python通過functool.wraps解決了這個問題:
在編寫裝飾器時,在實現(xiàn)前加入 @functools.wraps(func) 可以保證裝飾器不會對被裝飾函數(shù)造成影響。
特別說明其他要使用裝飾器的時候會有其他的寫法 比如直接返回被裝飾的函數(shù)。
def deco(func):
@functools.wraps(func) #
def wrapper(*args, **kw):
print 'begin call %s():' % (func.__name__)
return func(*args, **kw)
return wrapper
輸出
yangyiDBA:test yangyi$ python 1.py
begin call add():
2 + 5 = 7
end call add():
begin call now():
now is 2017-05-01 15:20:51.597859
end call now():
2.4 帶參數(shù)的裝飾器
如果裝飾器本身傳入?yún)?shù),就需要編寫一個返回decorator的高階函數(shù),寫出來會更復(fù)雜。比如,要自定義log的文本:
#!/usr/bin/env python
# coding:utf-8
import datetime
import functools
def deco(text):
def _deco(func):
def wrapper(*args, **kw):
print '%s, begin call %s():' % (text,func.__name__)
result=func(*args, **kw) # 如果函數(shù)無返回值 ,可以直接使用func(*args, **kw)
print '%s, end call %s():' % (text,func.__name__)
return result #這里 result 是為了func 有返回值,
return wrapper
return _deco
@deco("yangyi")
def add(x, y):
ret = x + y
print '{x} + {y} = {retval}'.format(x=x,y=y,retval=ret)
@deco("youzan")
def now():
print 'now is ', datetime.datetime.today()
add(2,5)
now()
測試結(jié)果:
yangyiDBA:test yangyi$ python 2.py
yangyi, begin call add():
2 + 5 = 7
yangyi, end call add():
youzan, begin call now():
now is 2017-05-01 18:47:54.728296
youzan, end call now():
2.5 Python內(nèi)置裝飾器
在Python中有三個內(nèi)置的裝飾器,都是跟class相關(guān)的:staticmethod、classmethod 和property。
staticmethod 是類靜態(tài)方法,其跟成員方法的區(qū)別是沒有 self 參數(shù),并且可以在類不進行實例化的情況下調(diào)用
classmethod 與成員方法的區(qū)別在于所接收的第一個參數(shù)不是 self (類實例的指針),而是cls(當(dāng)前類的具體類型)
property 是屬性的意思,表示可以通過通過類實例直接訪問的信息
2.6 跨文件調(diào)用,因為裝飾器本質(zhì)是一個函數(shù)。在工程實現(xiàn)里我們可以通過創(chuàng)建一個公用的decorator,作為基礎(chǔ)裝飾器供其他函數(shù)調(diào)用。
Python一切皆對象,函數(shù)也是,也可以賦值給其他變量,理解這點再去理解裝飾器就容易多了。
以上就是Python中如何淺談裝飾器,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道。