电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

舉例講解Python裝飾器

瀏覽:3日期:2022-07-01 11:36:15

在Python里面,函數可以作為參數傳入一個函數,函數也可以復制給變量,通過變量調用函數。裝飾器可以擴展一個函數的功能,為函數做一個裝飾器注解,可以把裝飾器里面定義的功能于所有函數提前執行,提升代碼的復用程度。

現在有這么個場景。

打卡

互聯網公司里面有各種員工,程序員,前臺...,程序員在打開電腦前,需要打卡,前臺要早點來開門(我也不清楚,誰開門,這里假定,前臺開門),前臺開門前也需要打卡。也就是說,打卡是所有員工的最先的公共動作,那么可以把打卡這個功能抽出來作為公共邏輯。

普通函數調用方法

自然想到,可以實現如下。

def di(f): print(’%s 打卡,滴...’ % f.__name__) return f()def boot(): print(’開機’)def open(): print(’開門’)if __name__ == ’__main__’: ''' 程序員開機之前,前臺開門之前,都需要先在門外指紋機打卡。 ''' di(boot) di(open)

定義了一個函數di(f),可以打印f.__name__即f的函數名信息,同時返回f()的執行結果。

注意:__name__如果作為模塊導入,module.__name__就是模塊自己的名字,如果模塊自己作為腳本執行,返回__main__。

執行結果:

boot 打卡,滴...開機open 打卡,滴...開門

這樣設計,如果有很多函數都要調用,就很麻煩,那么裝飾器就排上了用場。

簡單裝飾器 與 @語法糖

裝飾器:在代碼運行期間動態增加功能的方式,稱之為“裝飾器”(Decorator)。

簡單裝飾器

定義一個di(f)方法,還是把要執行的邏輯的函數作為參數傳入,里面定義一個wrapper函數,返回值是f的執行結果。在if __name__ == ’__main__’:里面,調用了這個裝飾器,不修改定義好了的函數,在運行期間動態添加功能'打卡'。

import functools# 簡單裝飾器def di(f): ''' 程序員開機之前,前臺開門之前,都需要先在門外指紋機打卡。 :param f: 傳入一個函數 :return: ''' # 把原始函數的__name__等屬性復制到wrapper() @functools.wraps(f) def wrapper(): print(’%s 打卡,滴...’ % f.__name__) return f() return wrapperdef boot(): print(’開機’)def open(): print(’開門’)if __name__ == ’__main__’: # 第一種,簡單裝飾器 a = di(boot) a1 = di(open) print(a.__name__) # 結果wrapper 加@functools.wraps(f)后結果為 boot a() a1()

di(boot)的返回值a就是wrapper函數,通過a()就調用了wrapper函數,得到boot的返回值。同理,di(open)一樣。

結果

bootboot 打卡,滴...開機open 打卡,滴...開門

由于di(boot)的返回值a就是wrapper函數,那么print(a.__name__)的結果就理所當然是是wrapper,我們希望是boot,怎么辦,functools.wraps(f)這個注解可以把原始函數boot的__name__等屬性復制到wrapper(),把這行代碼注釋也能運行,那么print(a.__name__)的結果就是wrapper。

第二種,@ 語法糖通過@語法糖,也能將裝飾器應用于函數上面,推薦。

import functoolsdef di(f): ''' 程序員開機之前,前臺開門之前,都需要先在門外指紋機打卡。 :param f: 傳入一個函數 :return: ''' # 把原始函數的__name__等屬性復制到wrapper() @functools.wraps(f) def wrapper(): print(’%s 打卡,滴...’ % f.__name__) return f() return wrapper# @ 語法糖@didef boot2(): print(’開機’)@didef open2(): print(’開門’) if __name__ == ’__main__’: # 第二種,@ 語法糖 boot2() open2()

@di標記相當于,a2 = di(boot2) a2()。不用這么麻煩,因為加了@符號標記,直接用boot2()調用裝飾器即可。

結果

boot2 打卡,滴...開機open2 打卡,滴...開門

業務邏輯函數需要參數

業務邏輯函數可能需要參數,比如:

def boot(name): print(’%s 開機’ % name)

那么,只需要將前面的裝飾器修改為:

import functools# 業務邏輯函數需要參數def di(f): ''' 程序員開機之前,前臺開門之前,都需要先在門外指紋機打卡。 :param f: 傳入一個函數 :return: ''' # 把原始函數的__name__等屬性復制到wrapper() @functools.wraps(f) def wrapper(*args, **kwargs): print(’%s 打卡,滴...’ % f.__name__) return f(*args, **kwargs) return wrapper@didef boot(name): print(’%s 開機’ % name)if __name__ == ’__main__’: boot(’keguang’)

結果:

boot 打卡,滴...keguang 開機

給wrapper也加上*args, **kwargs參數,在boot里面直接調用f(*args, **kwargs)即可。順便提一下:

*args:可以傳入一個數組參數 **kwargs:可以傳入一個k-v對參數

先后順序對應,數組參數在前。舉例:

def f(*args, **kwargs): print(’args=’, args) print(’kwargs=’, kwargs)print(f(1, 2, 3, a = ’a’, b = ’b’))# 結果# args= (1, 2, 3)# kwargs= {’a’: ’a’, ’b’: ’b’}帶參數的裝飾器

如果裝飾器也帶參數,比如現在如果某個員工早晨上班來得早< 9:00,咱可以做個表揚,那么相當于只需要在前面的di()外面套一層函數,di_args即可,在wrapper里面。使用這個參數

import functools# 帶參數的裝飾器def di_args(time): def di(f): ''' 程序員開機之前,前臺開門之前,都需要先在門外指紋機打卡。 :param f: 傳入一個函數 :return: ''' # 把原始函數的__name__等屬性復制到wrapper() @functools.wraps(f) def wrapper(*args, **kwargs): if time < ’9:00’:print(’來的真早,很棒。。。’) print(’%s 打卡,滴...’ % f.__name__) return f(*args, **kwargs) return wrapper return di@di_args(’8:00’)def boot(name): print(’%s 開機’ % name)if __name__ == ’__main__’: boot(’keguang’)

參數在@di_args(’8:00’)傳入即可,有點像java里面的注解。最后還是通過boot(’keguang’)調用即可,結果:

來的真早,很棒。。。boot 打卡,滴...keguang 開機

類裝飾器

類裝飾器主要依靠類的__call__方法,當使用 @ 形式將裝飾器附加到函數上時,就會調用此方法。

# 類裝飾器class di(object): def __init__(self, f): self._f = f def __call__(self, *args, **kwargs): print(’decorator start...’) self._f() print(’decorator end...’)@didef boot(): print(’開機’)if __name__ == ’__main__’: boot()

加上@di裝飾器標識,會用boot去實例化di類,然后執行__call__函數,object表示這個類可以傳入任何類型參數。運行結果

decorator start...開機decorator end...

裝飾器有一個典型的應用場景就是打log日志,如果所有邏輯都需要日志記錄程序的運行狀況,那么可以對這些邏輯(函數)加日志模塊裝飾器,就能達到相應目的。

以上就是舉例講解Python裝飾器的詳細內容,更多關于python裝飾器的資料請關注好吧啦網其它相關文章!

標簽: Python 編程
相關文章:
主站蜘蛛池模板: 预制直埋蒸汽保温管-直埋管道-聚氨酯发泡保温管厂家 - 唐山市吉祥保温工贸有限公司 | 深圳高新投三江工业消防解决方案提供厂家_服务商_园区智慧消防_储能消防解决方案服务商_高新投三江 | 气弹簧定制-气动杆-可控气弹簧-不锈钢阻尼器-工业气弹簧-可调节气弹簧厂家-常州巨腾气弹簧供应商 | 间苯二酚,间苯二酚厂家-淄博双和化工 | 中医中药治疗血小板减少-石家庄血液病肿瘤门诊部 | 成都思迪机电技术研究所-四川成都思迪编码器 | 武汉天安盾电子设备有限公司 - 安盾安检,武汉安检门,武汉安检机,武汉金属探测器,武汉测温安检门,武汉X光行李安检机,武汉防爆罐,武汉车底安全检查,武汉液体探测仪,武汉安检防爆设备 | 纯化水设备-EDI-制药-实验室-二级反渗透-高纯水|超纯水设备 | 槽钢冲孔机,槽钢三面冲,带钢冲孔机-山东兴田阳光智能装备股份有限公司 | 医院专用门厂家报价-医用病房门尺寸大全-抗菌木门品牌推荐 | 耐磨陶瓷管道_除渣器厂家-淄博浩瀚陶瓷科技有限公司 | 东莞螺丝|东莞螺丝厂|东莞不锈钢螺丝|东莞组合螺丝|东莞精密螺丝厂家-东莞利浩五金专业紧固件厂家 | 东莞螺杆空压机_永磁变频空压机_节能空压机_空压机工厂批发_深圳螺杆空压机_广州螺杆空压机_东莞空压机_空压机批发_东莞空压机工厂批发_东莞市文颖设备科技有限公司 | 恒压供水控制柜|无负压|一体化泵站控制柜|PLC远程调试|MCGS触摸屏|自动控制方案-联致自控设备 | 自动化改造_智虎机器人_灌装机_贴标机-上海圣起包装机械 | 上海恒驭仪器有限公司-实验室平板硫化机-小型平板硫化机-全自动平板硫化机 | 湿地保护| 粉末包装机-给袋式包装机-全自动包装机-颗粒-液体-食品-酱腌菜包装机生产线【润立机械】 | 深圳侦探联系方式_深圳小三调查取证公司_深圳小三分离机构 | 阿里巴巴诚信通温州、台州、宁波、嘉兴授权渠道商-浙江联欣科技提供阿里会员办理 | 短信通106短信接口验证码接口群发平台_国际短信接口验证码接口群发平台-速度网络有限公司 | 世界箱包品牌十大排名,女包小众轻奢品牌推荐200元左右,男包十大奢侈品牌排行榜双肩,学生拉杆箱什么品牌好质量好 - Gouwu3.com | 低压载波电能表-单相导轨式电能表-华邦电力科技股份有限公司-智能物联网综合管理平台 | 贴板式电磁阀-不锈钢-气动上展式放料阀-上海弗雷西阀门有限公司 工业机械三维动画制作 环保设备原理三维演示动画 自动化装配产线三维动画制作公司-南京燃动数字 | 防渗土工膜|污水处理防渗膜|垃圾填埋场防渗膜-泰安佳路通工程材料有限公司 | 全钢实验台,实验室工作台厂家-无锡市辰之航装饰材料有限公司 | 低浓度恒温恒湿称量系统,强光光照培养箱-上海三腾仪器有限公司 | 铝箔-铝板-花纹铝板-铝型材-铝棒管-上海百亚金属材料有限公司 | 杭州代理记账费用-公司注销需要多久-公司变更监事_杭州福道财务管理咨询有限公司 | 磁力去毛刺机_去毛刺磁力抛光机_磁力光饰机_磁力滚抛机_精密金属零件去毛刺机厂家-冠古科技 | 361°官方网站| 圆周直径尺-小孔内视镜-纤维研磨刷-东莞市高腾达精密工具 | 电动液压篮球架_圆管地埋式篮球架_移动平箱篮球架-强森体育 | 上海乾拓贸易有限公司-日本SMC电磁阀_德国FESTO电磁阀_德国FESTO气缸 | 招商帮-一站式网络营销服务|搜索营销推广|信息流推广|短视视频营销推广|互联网整合营销|网络推广代运营|招商帮企业招商好帮手 | 安徽成考网-安徽成人高考网| 胶水,胶粘剂,AB胶,环氧胶,UV胶水,高温胶,快干胶,密封胶,结构胶,电子胶,厌氧胶,高温胶水,电子胶水-东莞聚力-聚厉胶粘 | 扬尘监测_扬尘监测系统_带证扬尘监测设备 - 郑州港迪科技有限公司 | 隐形纱窗|防护纱窗|金刚网防盗纱窗|韦柏纱窗|上海青木装潢制品有限公司|纱窗国标起草单位 | 新能源汽车教学设备厂家报价[汽车教学设备运营18年]-恒信教具 | 空冷器|空气冷却器|空水冷却器-无锡赛迪森机械有限公司[官网] |