網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
Python裝飾器用法
Python的裝飾器是個(gè)好東西,它能干很多事情。
但對(duì)于新手,它看起來(lái)似乎沒(méi)那么簡(jiǎn)單。
但事實(shí)上,裝飾器本身也只是個(gè)函數(shù)。
import time
def log(func):
? ? def wrapper(*args, **kwargs):
? ? ? ? start = time.time()
? ? ? ? result = func(*args, **kwargs)
? ? ? ? end = time.time()
? ? ? ? print("The func '{}' used {}s.".format(func.__name__, end-start))
? ? ? ? return result
? ? return warpper
這一個(gè)裝飾器,當(dāng)我們這樣使用時(shí)
@log
def fucok(name):
? ? """Fucok someone"""
? ? print("Fucok", name)
它只是執(zhí)行了fucok = log(fucok)這樣一句代碼而已。
也就是說(shuō),我們表面上是用fucok("myself"),事實(shí)上執(zhí)行的都是log(fucok)("myself")。因?yàn)镻ython里面都是對(duì)象嘛。
同樣的道理,假設(shè)我們定義了一個(gè)帶參數(shù)的裝飾器logging,它實(shí)際上執(zhí)行的是
func = logging(arguments)(func)
也就是上面那個(gè)不帶參數(shù)的裝飾器多定義一層就行了。
import time
def logging(arguments):
? ? def log(func):
? ? ? ? def warpper(*args, **kwargs):
? ? ? ? ? ? start = time.time()
? ? ? ? ? ? result = func(*args, **kwargs)
? ? ? ? ? ? end = time.time()
? ? ? ? ? ? print("The func '{}' used {}s.".format(func.__name__, end-start))
? ? ? ? ? ? return result
? ? ? ? return warpper
? ? # do something
? ? return log
但,當(dāng)我們使用一個(gè)裝飾器之后,它會(huì)將原本的函數(shù)元信息給覆蓋掉。譬如:函數(shù)名稱(chēng),函數(shù)文檔等等。
例如上例
print(fucok.__name__)
print(fucok.__doc__)
你會(huì)發(fā)現(xiàn),函數(shù)信息全部沒(méi)了!fucok它不叫fucok,改名叫wrapper了。它的文檔也變成了none。
解決辦法很簡(jiǎn)單,定義裝飾器的時(shí)候用warps裝飾器裝飾接受原函數(shù)參數(shù)的那一層就行了。
這個(gè)來(lái)自functools模塊的裝飾器能幫你復(fù)制函數(shù)的元信息到被綁定的函數(shù)身上。
修改裝飾器如下(其實(shí)就加了一行代碼hhh)
import time
from functools import wraps
def log(func):
? ? @wraps(func)
? ? def warpper(*args, **kwargs):
? ? ? ? start = time.time()
? ? ? ? result = func(*args, **kwargs)
? ? ? ? end = time.time()
? ? ? ? print("The func '{}' used {}s.".format(func.__name__, end-start))
? ? ? ? return result
? ? return warpper
當(dāng)我們?cè)龠\(yùn)行
print(fucok.__name__)
print(fucok.__doc__)
就能看到函數(shù)的的元信息沒(méi)變了。
裝飾器定義時(shí)加@wraps是個(gè)好習(xí)慣。
一個(gè)較為實(shí)用的裝飾器demo在該專(zhuān)題的另一篇文章:函數(shù)參數(shù)類(lèi)型檢查
總結(jié)
原文鏈接:https://www.jianshu.com/p/4416e291c64d
相關(guān)推薦
- 2022-10-28 Pandas實(shí)現(xiàn)兩個(gè)表的連接功能的方法詳解_python
- 2022-06-07 教你使用Jenkins集成Harbor自動(dòng)發(fā)布鏡像_docker
- 2022-09-05 Hbase之查看RowKey所在Region
- 2022-08-29 Python神器之Pampy模式匹配庫(kù)的用法詳解_python
- 2022-03-27 Docker下安裝Mongo4.2及客戶(hù)端工具連接Mongo_docker
- 2022-08-27 教你使用Python的pygame模塊實(shí)現(xiàn)拼圖游戲_python
- 2022-04-15 C語(yǔ)言?指針數(shù)組進(jìn)階詳解_C 語(yǔ)言
- 2023-03-15 React受控組件與非受控組件實(shí)例分析講解_React
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支