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

首頁 > 編程 > Python > 正文

Python中裝飾器高級用法詳解

2020-02-16 11:17:19
字體:
來源:轉載
供稿:網友

在Python中,裝飾器一般用來修飾函數,實現公共功能,達到代碼復用的目的。在函數定義前加上@xxxx,然后函數就注入了某些行為,很神奇!然而,這只是語法糖而已。

場景

假設,有一些工作函數,用來對數據做不同的處理:

def work_bar(data):  passdef work_foo(data):  pass

我們想在函數調用前/后輸出日志,怎么辦?

傻瓜解法

logging.info('begin call work_bar')work_bar(1)logging.info('call work_bar done')

如果有多處代碼調用呢?想想就怕!

函數包裝

傻瓜解法無非是有太多代碼冗余,每次函數調用都要寫一遍logging。可以把這部分冗余邏輯封裝到一個新函數里:

def smart_work_bar(data):  logging.info('begin call: work_bar')  work_bar(data)  logging.info('call doen: work_bar')

這樣,每次調用smart_work_bar即可:

smart_work_bar(1)# ...smart_work_bar(some_data)

通用閉包

看上去挺完美……然而,當work_foo也有同樣的需要時,還要再實現一遍smart_work_foo嗎?這樣顯然不科學呀!

別急,我們可以用閉包:

def log_call(func):  def proxy(*args, **kwargs):    logging.info('begin call: {name}'.format(name=func.func_name))    result = func(*args, **kwargs)    logging.info('call done: {name}'.format(name=func.func_name))    return result  return proxy

這個函數接收一個函數對象(被代理函數)作為參數,返回一個代理函數。調用代理函數時,先輸出日志,然后調用被代理函數,調用完成后再輸出日志,最后返回調用結果。這樣,不就達到通用化的目的了嗎?——對于任意被代理函數func,log_call均可輕松應對。

smart_work_bar = log_call(work_bar)smart_work_foo = log_call(work_foo)smart_work_bar(1)smart_work_foo(1)# ...smart_work_bar(some_data)smart_work_foo(some_data)

第1行中,log_call接收參數work_bar,返回一個代理函數proxy,并賦給smart_work_bar。第4行中,調用smart_work_bar,也就是代理函數proxy,先輸出日志,然后調用func也就是work_bar,最后再輸出日志。注意到,代理函數中,func與傳進去的work_bar對象緊緊關聯在一起了,這就是閉包。

再提一下,可以覆蓋被代理函數名,以smart_為前綴取新名字還是顯得有些累贅:

work_bar = log_call(work_bar)work_foo = log_call(work_foo)work_bar(1)work_foo(1)

語法糖

先來看看以下代碼:

def work_bar(data):  passwork_bar = log_call(work_bar)def work_foo(data):  passwork_foo = log_call(work_foo)

雖然代碼沒有什么冗余了,但是看是去還是不夠直觀。這時候,語法糖來了~~~

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 仁寿县| 灌云县| 朝阳市| 通海县| 吕梁市| 鄂州市| 荥经县| 宝鸡市| 汤阴县| 忻州市| 三亚市| 盐边县| 天镇县| 东光县| 军事| 来宾市| 桓台县| 大洼县| 抚松县| 夏邑县| 宜春市| 南安市| 界首市| 西藏| 崇义县| 汾阳市| 南平市| 泸溪县| 昆山市| 韶关市| 旺苍县| 永州市| 萨嘎县| 叶城县| 潞西市| 桑植县| 五台县| 鄂托克前旗| 东明县| 靖远县| 舟曲县|