国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

python 裝飾器的使用與要點(diǎn)

瀏覽:2日期:2022-06-18 15:04:07
目錄一、裝飾器使用場(chǎng)景二、為什么需要裝飾器1、先來(lái)看一個(gè)簡(jiǎn)單例子:2、增加需求3、又有需求三、基礎(chǔ)裝飾器入門1、裝飾器語(yǔ)法糖2、對(duì)帶參數(shù)的函數(shù)進(jìn)行裝飾3、函數(shù)參數(shù)數(shù)量不確定4、裝飾器帶參數(shù)5、functools.wraps6、實(shí)現(xiàn)帶參數(shù)和不帶參數(shù)的裝飾器自適應(yīng)三、類裝飾器1、類裝飾器 2、繼承擴(kuò)展類裝飾器一、裝飾器使用場(chǎng)景

經(jīng)常用于有切面需求的場(chǎng)景,比如:插入日志、性能測(cè)試、事務(wù)處理、緩存、權(quán)限校驗(yàn)等場(chǎng)景。裝飾器是解決這類問題的絕佳設(shè)計(jì),有了裝飾器,我們就可以抽離出大量與函數(shù)功能本身無(wú)關(guān)的雷同代碼并繼續(xù)重用。

概括的講,裝飾器的作用就是為已經(jīng)存在的對(duì)象添加額外的功能。

二、為什么需要裝飾器1、先來(lái)看一個(gè)簡(jiǎn)單例子:

def foo():print(’i am foo’)2、增加需求

現(xiàn)在有一個(gè)新的需求,希望可以記錄下函數(shù)的執(zhí)行日志,于是在代碼中添加日志代碼:

def foo(): print(’i am foo’) print('foo is running')3、又有需求

假設(shè)現(xiàn)在有100個(gè)函數(shù)需要增加這個(gè)需求,并且后續(xù)可能還要對(duì)這一百個(gè)函數(shù)都增加執(zhí)行前打印日志的需求,怎么辦?還一個(gè)個(gè)改嗎?

當(dāng)然不了,這樣會(huì)造成大量雷同的代碼,為了減少重復(fù)寫代碼,我們可以這樣做,重新定義一個(gè)函數(shù):專門處理日志 ,日志處理完之后再執(zhí)行真正的業(yè)務(wù)代碼。

def use_logging(func): print('%s is running' % func.__name__) func()def bar(): print(’i am bar’)use_logging(bar)運(yùn)行結(jié)果:#bar is running#i am bar

函數(shù)use_logging就是裝飾器,它把執(zhí)行真正業(yè)務(wù)方法的func包裹在函數(shù)里面,看起來(lái)像bar被use_logging裝飾了。在這個(gè)例子中,函數(shù)進(jìn)入和退出時(shí) ,被稱為一個(gè)橫切面(Aspect),這種編程方式被稱為面向切面的編程(Aspect-Oriented Programming)。

通過以上use_logging函數(shù)我們?cè)黾恿巳罩竟δ埽还芤院笥卸嗌俸瘮?shù)需要增加日志或者修改日志的格式我們只需要修改use_logging函數(shù),并執(zhí)行use_logging(被裝飾的函數(shù))就達(dá)到了我們想要的效果。

def use_logging(func): print('%s is running' % func.__name__) return func@use_loggingdef bar(): print(’i am bar’)bar()三、基礎(chǔ)裝飾器入門1、裝飾器語(yǔ)法糖

python提供了@符號(hào)作為裝飾器的語(yǔ)法糖,使我們更方便的應(yīng)用裝飾函數(shù);但使用語(yǔ)法糖要求裝飾函數(shù)必須return一個(gè)函數(shù)對(duì)象。因此我們將上面的func函數(shù)使用內(nèi)嵌函數(shù)包裹并return。

裝飾器相當(dāng)于執(zhí)行了裝飾函數(shù)use_loggin后又返回被裝飾函數(shù)bar,因此bar()被調(diào)用的時(shí)候相當(dāng)于執(zhí)行了兩個(gè)函數(shù)。等價(jià)于use_logging(bar)()

def use_logging(func): def _deco():print('%s is running' % func.__name__)func() return _deco@use_loggingdef bar(): print(’i am bar’)bar()2、對(duì)帶參數(shù)的函數(shù)進(jìn)行裝飾

現(xiàn)在我們的參數(shù)需要傳入兩個(gè)參數(shù)并計(jì)算值,因此我們需要對(duì)內(nèi)層函數(shù)進(jìn)行改動(dòng)傳入我們的兩個(gè)參數(shù)a和b,等價(jià)于use_logging(bar)(1,2)

def use_logging(func): def _deco(a,b):print('%s is running' % func.__name__)func(a,b) return _deco@use_loggingdef bar(a,b): print(’i am bar:%s’%(a+b))bar(1,2)

我們裝飾的函數(shù)可能參數(shù)的個(gè)數(shù)和類型都不一樣,每一次我們都需要對(duì)裝飾器做修改嗎?這樣做當(dāng)然是不科學(xué)的,因此我們使用python的變長(zhǎng)參數(shù)*args和**kwargs來(lái)解決我們的參數(shù)問題。

3、函數(shù)參數(shù)數(shù)量不確定

不帶參數(shù)裝飾器版本,這個(gè)格式適用于不帶參數(shù)的裝飾器。

經(jīng)過以下修改,我們已經(jīng)適應(yīng)了各種長(zhǎng)度和類型的參數(shù)。這個(gè)版本的裝飾器可以裝飾任意類型的無(wú)參數(shù)函數(shù)。

def use_logging(func): def _deco(*args,**kwargs):print('%s is running' % func.__name__)func(*args,**kwargs) return _deco@use_loggingdef bar(a,b): print(’i am bar:%s’%(a+b))@use_loggingdef foo(a,b,c): print(’i am bar:%s’%(a+b+c))bar(1,2)foo(1,2,3)4、裝飾器帶參數(shù)

帶參數(shù)的裝飾器,這個(gè)格式適用于帶參數(shù)的裝飾器。

某些情況我們需要讓裝飾器帶上參數(shù),那就需要編寫一個(gè)返回一個(gè)裝飾器的高階函數(shù),寫出來(lái)會(huì)更復(fù)雜。比如:

#! /usr/bin/env python# -*- coding:utf-8 -*-# __author__ = 'TKQ'def use_logging(level): def _deco(func):def __deco(*args, **kwargs): if level == 'warn':print '%s is running' % func.__name__ return func(*args, **kwargs)return __deco return _deco@use_logging(level='warn')def bar(a,b): print(’i am bar:%s’%(a+b))bar(1,3)# 等價(jià)于use_logging(level='warn')(bar)(1,3)5、functools.wraps

使用裝飾器極大地復(fù)用了代碼,但是他有一個(gè)缺點(diǎn)就是原函數(shù)的元信息不見了,比如函數(shù)的docstring、__name__、參數(shù)列表,先看例子:

def use_logging(func): def _deco(*args,**kwargs):print('%s is running' % func.__name__)func(*args,**kwargs) return _deco@use_loggingdef bar(): print(’i am bar’) print(bar.__name__)bar()#bar is running#i am bar#_deco#函數(shù)名變?yōu)開deco而不是bar,這個(gè)情況在使用反射的特性的時(shí)候就會(huì)造成問題。因此引入了functools.wraps解決這個(gè)問題。

使用functools.wraps:

import functoolsdef use_logging(func): @functools.wraps(func) def _deco(*args,**kwargs):print('%s is running' % func.__name__)func(*args,**kwargs) return _deco@use_loggingdef bar(): print(’i am bar’) print(bar.__name__)bar()#result:#bar is running#i am bar#bar ,這個(gè)結(jié)果是我們想要的。OK啦!6、實(shí)現(xiàn)帶參數(shù)和不帶參數(shù)的裝飾器自適應(yīng)

import functoolsdef use_logging(arg): if callable(arg):#判斷參入的參數(shù)是否是函數(shù),不帶參數(shù)的裝飾器調(diào)用這個(gè)分支@functools.wraps(arg)def _deco(*args,**kwargs): print('%s is running' % arg.__name__) arg(*args,**kwargs)return _deco else:#帶參數(shù)的裝飾器調(diào)用這個(gè)分支def _deco(func): @functools.wraps(func) def __deco(*args, **kwargs):if arg == 'warn': print 'warn%s is running' % func.__name__return func(*args, **kwargs) return __decoreturn _deco@use_logging('warn')# @use_loggingdef bar(): print(’i am bar’) print(bar.__name__)bar()三、類裝飾器

使用類裝飾器可以實(shí)現(xiàn)帶參數(shù)裝飾器的效果,但實(shí)現(xiàn)的更加優(yōu)雅簡(jiǎn)潔,而且可以通過繼承來(lái)靈活的擴(kuò)展.

1、類裝飾器

class loging(object): def __init__(self,level='warn'):self.level = level def __call__(self,func):@functools.wraps(func)def _deco(*args, **kwargs): if self.level == 'warn':self.notify(func) return func(*args, **kwargs)return _deco def notify(self,func):# logit只打日志,不做別的print '%s is running' % func.__name__@loging(level='warn')#執(zhí)行__call__方法def bar(a,b): print(’i am bar:%s’%(a+b))bar(1,3) 2、繼承擴(kuò)展類裝飾器

class email_loging(Loging): ’’’ 一個(gè)loging的實(shí)現(xiàn)版本,可以在函數(shù)調(diào)用時(shí)發(fā)送email給管理員 ’’’ def __init__(self, email=’[email protected]’, *args, **kwargs):self.email = emailsuper(email_loging, self).__init__(*args, **kwargs) def notify(self,func):# 發(fā)送一封email到self.emailprint '%s is running' % func.__name__print 'sending email to %s' %self.email@email_loging(level='warn')def bar(a,b): print(’i am bar:%s’%(a+b))bar(1,3)

以上就是python 裝飾器的使用與要點(diǎn)的詳細(xì)內(nèi)容,更多關(guān)于python 裝飾器的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 国产精品亚洲第一区二区三区 | 97久久精品午夜一区二区 | 高清大学生毛片一级 | 免费一级在线观看 | 久久狠狠色狠狠色综合 | 成人看片黄a免费 | 131美女爱做免费毛片 | 一级免费a | 亚洲成人黄色在线 | 亚洲国产成人久久精品影视 | www.av在线免费观看 | 欧美视频在线观看免费精品欧美视频 | 欧美成人影院 在线播放 | 国产r67194吃奶视频 | 久久久久国产精品免费看 | 日韩一级欧美一级毛片在线 | 亚洲成a人片在线看 | 欧美视频在线观看 | 久草免费精品视频 | 亚洲国产精品日韩高清秒播 | 超91精品手机国产在线 | 国产精品久久久香蕉 | 亚洲精品一区二区三区四区手机版 | 亚洲精品一区二区三区在线观看 | 亚洲第一区视频 | 久久福利青草免费精品 | 美女三级在线 | 亚洲欧美精品一区二区 | 久久久久久久久久久福利观看 | 一级高清毛片免费a级高清毛片 | 亚洲一级特黄特黄的大片 | 国产精品久久久久一区二区三区 | 亚洲美女视频在线观看 | 久久riav.com| 一级特黄牲大片免费视频 | 成人a级| 美女亚洲综合 | 国产一级一级片 | 亚洲欧美另类自拍第一页 | 福利视频美女国产精品 | 中文字幕在线不卡 |