>> def now(): ... print '2013-12-25' ... >>> f = now >>> f() 2013-12-25 函數(shù)對(duì)象有一個(gè)__name__屬性,可以拿到函數(shù)的名字: >>> now._" />

国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識(shí)百科 - 正文

舉例講解Python中裝飾器的用法

來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 14:39:28
文檔

舉例講解Python中裝飾器的用法

舉例講解Python中裝飾器的用法:由于函數(shù)也是一個(gè)對(duì)象,而且函數(shù)對(duì)象可以被賦值給變量,所以,通過變量也能調(diào)用該函數(shù)。 >>> def now(): ... print '2013-12-25' ... >>> f = now >>> f() 2013-12-25 函數(shù)對(duì)象有一個(gè)__name__屬性,可以拿到函數(shù)的名字: >>> now._
推薦度:
導(dǎo)讀舉例講解Python中裝飾器的用法:由于函數(shù)也是一個(gè)對(duì)象,而且函數(shù)對(duì)象可以被賦值給變量,所以,通過變量也能調(diào)用該函數(shù)。 >>> def now(): ... print '2013-12-25' ... >>> f = now >>> f() 2013-12-25 函數(shù)對(duì)象有一個(gè)__name__屬性,可以拿到函數(shù)的名字: >>> now._

由于函數(shù)也是一個(gè)對(duì)象,而且函數(shù)對(duì)象可以被賦值給變量,所以,通過變量也能調(diào)用該函數(shù)。

>>> def now():
... print '2013-12-25'
...
>>> f = now
>>> f()
2013-12-25

函數(shù)對(duì)象有一個(gè)__name__屬性,可以拿到函數(shù)的名字:

>>> now.__name__
'now'
>>> f.__name__
'now'

現(xiàn)在,假設(shè)我們要增強(qiáng)now()函數(shù)的功能,比如,在函數(shù)調(diào)用前后自動(dòng)打印日志,但又不希望修改now()函數(shù)的定義,這種在代碼運(yùn)行期間動(dòng)態(tài)增加功能的方式,稱之為“裝飾器”(Decorator)。

本質(zhì)上,decorator就是一個(gè)返回函數(shù)的高階函數(shù)。所以,我們要定義一個(gè)能打印日志的decorator,可以定義如下:

def log(func):
 def wrapper(*args, **kw):
 print 'call %s():' % func.__name__
 return func(*args, **kw)
 return wrapper

觀察上面的log,因?yàn)樗且粋€(gè)decorator,所以接受一個(gè)函數(shù)作為參數(shù),并返回一個(gè)函數(shù)。我們要借助Python的@語法,把decorator置于函數(shù)的定義處:

@log
def now():
 print '2013-12-25'

調(diào)用now()函數(shù),不僅會(huì)運(yùn)行now()函數(shù)本身,還會(huì)在運(yùn)行now()函數(shù)前打印一行日志:

>>> now()
call now():
2013-12-25

把@log放到now()函數(shù)的定義處,相當(dāng)于執(zhí)行了語句:

now = log(now)

由于log()是一個(gè)decorator,返回一個(gè)函數(shù),所以,原來的now()函數(shù)仍然存在,只是現(xiàn)在同名的now變量指向了新的函數(shù),于是調(diào)用now()將執(zhí)行新函數(shù),即在log()函數(shù)中返回的wrapper()函數(shù)。

wrapper()函數(shù)的參數(shù)定義是(*args, **kw),因此,wrapper()函數(shù)可以接受任意參數(shù)的調(diào)用。在wrapper()函數(shù)內(nèi),首先打印日志,再緊接著調(diào)用原始函數(shù)。

如果decorator本身需要傳入?yún)?shù),那就需要編寫一個(gè)返回decorator的高階函數(shù),寫出來會(huì)更復(fù)雜。比如,要自定義log的文本:

def log(text):
 def decorator(func):
 def wrapper(*args, **kw):
 print '%s %s():' % (text, func.__name__)
 return func(*args, **kw)
 return wrapper
 return decorator

這個(gè)3層嵌套的decorator用法如下:

@log('execute')
def now():
 print '2013-12-25'

執(zhí)行結(jié)果如下:

>>> now()
execute now():
2013-12-25

和兩層嵌套的decorator相比,3層嵌套的效果是這樣的:

>>> now = log('execute')(now)

我們來剖析上面的語句,首先執(zhí)行l(wèi)og('execute'),返回的是decorator函數(shù),再調(diào)用返回的函數(shù),參數(shù)是now函數(shù),返回值最終是wrapper函數(shù)。

以上兩種decorator的定義都沒有問題,但還差最后一步。因?yàn)槲覀冎v了函數(shù)也是對(duì)象,它有__name__等屬性,但你去看經(jīng)過decorator裝飾之后的函數(shù),它們的__name__已經(jīng)從原來的'now'變成了'wrapper':

>>> now.__name__
'wrapper'

因?yàn)榉祷氐哪莻€(gè)wrapper()函數(shù)名字就是'wrapper',所以,需要把原始函數(shù)的__name__等屬性復(fù)制到wrapper()函數(shù)中,否則,有些依賴函數(shù)簽名的代碼執(zhí)行就會(huì)出錯(cuò)。

不需要編寫wrapper.__name__ = func.__name__這樣的代碼,Python內(nèi)置的functools.wraps就是干這個(gè)事的,所以,一個(gè)完整的decorator的寫法如下:

import functools

def log(func):
 @functools.wraps(func)
 def wrapper(*args, **kw):
 print 'call %s():' % func.__name__
 return func(*args, **kw)
 return wrapper

或者針對(duì)帶參數(shù)的decorator:

import functools

def log(text):
 def decorator(func):
 @functools.wraps(func)
 def wrapper(*args, **kw):
 print '%s %s():' % (text, func.__name__)
 return func(*args, **kw)
 return wrapper
 return decorator

import functools是導(dǎo)入functools模塊。模塊的概念稍候講解。現(xiàn)在,只需記住在定義wrapper()的前面加上@functools.wraps(func)即可。
小結(jié)

在面向?qū)ο螅∣OP)的設(shè)計(jì)模式中,decorator被稱為裝飾模式。OOP的裝飾模式需要通過繼承和組合來實(shí)現(xiàn),而Python除了能支持OOP的decorator外,直接從語法層次支持decorator。Python的decorator可以用函數(shù)實(shí)現(xiàn),也可以用類實(shí)現(xiàn)。

decorator可以增強(qiáng)函數(shù)的功能,定義起來雖然有點(diǎn)復(fù)雜,但使用起來非常靈活和方便。

請(qǐng)編寫一個(gè)decorator,能在函數(shù)調(diào)用的前后打印出'begin call'和'end call'的日志。

再思考一下能否寫出一個(gè)@log的decorator,使它既支持:

@log
def f():
 pass

又支持:

@log('execute')
def f():
 pass

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

舉例講解Python中裝飾器的用法

舉例講解Python中裝飾器的用法:由于函數(shù)也是一個(gè)對(duì)象,而且函數(shù)對(duì)象可以被賦值給變量,所以,通過變量也能調(diào)用該函數(shù)。 >>> def now(): ... print '2013-12-25' ... >>> f = now >>> f() 2013-12-25 函數(shù)對(duì)象有一個(gè)__name__屬性,可以拿到函數(shù)的名字: >>> now._
推薦度:
標(biāo)簽: 使用 用法 使用的
  • 熱門焦點(diǎn)

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 国产精品久久久久一区二区 | 亚洲男同在线观看 | 成人一a毛片免费视频 | 91久久综合九色综合欧美98 | 精品一区二区三区四区电影 | 日本精品一区二区三区在线观看 | 亚洲 欧美 日韩 另类 | 欧美在线二区 | 欧美自拍亚洲 | 国产精品伦理久久久久 | 欧美日韩网 | 精品视频网站 | 国产精品不卡在线观看 | 广东东莞一级毛片免费 | 美女a毛片 | 亚洲欧洲综合 | 欧美综合自拍亚洲综合百度 | 亚州色图欧美色图 | 香港经典a毛片免费观看…伊人色综合久久 | 国产欧美日韩高清专区手机版 | 精品一区 二区三区免费毛片 | 日韩高清第一页 | 国产麻豆精品免费密入口 | 国产精品va一区二区三区 | 亚洲伦理中文字幕一区 | 国产网站精品 | 亚洲精品乱码久久久久久中文字幕 | 一级特黄女毛毛片 | 国产成人亚洲综合一区 | 国产一区二区福利久久 | 亚洲专区路线一路线二天美 | 91一区二区在线观看精品 | 国产在线观看中文字幕 | 国产在线中文字幕 | 成人精品视频在线观看 | 亚洲国语在线视频手机在线 | 欧美日韩高清 | 精品欧美一区二区三区在线 | 国产成人亚洲综合91精品555 | 高清视频一区 | 国内精品视频在线观看 |