python基礎四:裝飾器

來源:互聯網
上載者:User

標籤:就是   歡迎來到   函數應用   use   函數定義   foo   應用   本質   ptime   

裝飾器本質:就是函數,功能是為其他函數添加附加功能

裝飾器原則:

  1. 不修改被修飾函數的原始碼
  2. 不修改修飾函數的調用方式

裝飾器的知識儲備:

裝飾器 = 高階函數 + 函數嵌套 + 閉包

初識裝飾器

先看一個需求:下面這個函數用來計算1到20的和

def calc(l):    res = 0    for i in l:        time.sleep(0.01)        res += i    return resresult = calc(range(1,21))print(result)

但現在需求有變,不僅要計算1到20的和,還需要計算該函數啟動並執行時間,此時裝飾器就應需而生

import timedef timer(func):    def wrapper(*args,**kwargs):        start_time = time.time()        res = func(*args,**kwargs)        stop_time = time.time()        print(‘函數啟動並執行時間為:%s‘ % (stop_time - start_time))        return res    return wrapper@timerdef calc(l):    res = 0    for i in l:        time.sleep(0.01)        res += i    return resresult = calc(range(1,21))print(result)

運行結果如下:

函數啟動並執行時間為:0.2048475742340088210

上面的timer函數就是calc函數的裝飾器

高階函數

高階函數定義:
1.函數接收的參數是一個函數名

2.函數的傳回值是一個函數名

3.滿足上述條件任意一個,都可稱之為高階函數

高階函數樣本
def foo():    print(‘我的函數名作為參數傳給高階函數‘)def gao_jie1(func):    print(‘我就是高階函數1,我接收的參數名是%s‘ %func)    func()def gao_jie2(func):    print(‘我就是高階函數2,我的傳回值是%s‘ %func)    return funcgao_jie1(foo)gao_jie2(foo)
把函數當作參數傳給高階函數
#高階函數應用1:把函數當做參數傳給高階函數import timedef foo():    print(‘from the foo‘)def timmer(func):    start_time=time.time()    func()    stop_time=time.time()    print(‘函數%s 已耗用時間是%s‘ %(func,stop_time-start_time))timmer(foo)#總結:我們確實為函數foo增加了foo已耗用時間的功能,但是foo原來的執行方式是foo(),現在我們需要調用高階函數timmer(foo),改變了函數的調用方式
函數傳回值是函數名
#高階函數應用2:把函數名當做參數傳給高階函數,高階函數直接返回函數名import timedef foo():    print(‘from the foo‘)def timmer(func):    start_time=time.time()    return func    stop_time=time.time()    print(‘函數%s 已耗用時間是%s‘ %(func,stop_time-start_time))foo=timmer(foo)foo()#總結:我們確實沒有改變foo的調用方式,但是我們也沒有為foo增加任何新功能

高階函數總結
1.函數接收的參數是一個函數名
  作用:在不修改函數原始碼的前提下,為函數添加新功能,
  不足:會改變函數的調用方式
2.函數的傳回值是一個函數名
  作用:不修改函數的調用方式
  不足:不能添加新功能

函數嵌套
def father(name):    print(‘from father %s‘ %name)    def son():        print(‘from son‘)        def grandson():            print(‘from grandson‘)        grandson()    son()father(‘Poe‘)
閉包
‘‘‘閉包:在一個作用哉裡放放定義變數,相當於打了一個包‘‘‘def father(name):    def son():        print(‘My father is %s‘ %name)        def grandson():            print(‘my grandpa is %s‘ %name)        grandson()    son()father(‘Poe‘)
無參數裝飾器

無參裝飾器=進階函數+函數嵌套

基本架構

‘‘‘這就是一個實現 裝飾器最基本的架子‘‘‘def timer(func):    def wrapper():        func()    return wrapper()

回到上面需要計算函數已耗用時間的需求,在不使用裝飾器的情況下加上以下代碼

import timedef timer(func):    def wrapper():        startTime = time.time()        func()        stopTime = time.time()        print(‘函數已耗用時間為:%s‘ % (stopTime - startTime))    return wrapperdef test():    time.sleep(3)    print(‘test函數運行完畢‘)res = timer(test)res()

使用裝飾器

import timedef timer(func):    def wrapper():        startTime = time.time()        func()        stopTime = time.time()        print(‘函數已耗用時間為:%s‘ % (stopTime - startTime))    return wrapper@timer  #相當於test = timer(test)def test():    time.sleep(3)    print(‘test函數運行完畢‘)test()

傳回值問題
如果test函數中有傳回值怎麼返回呢?test函數被調用時,實質就是調用wrapper函數,如果要返回test函數中的值,必須要在wrapper函數中將該值返回

import timedef timer(func):    def wrapper():        startTime = time.time()        res = func()        stopTime = time.time()        print(‘該函數已耗用時間為:%s‘ % (stopTime - startTime))        return res    return wrapper@timerdef test():    time.sleep(1)    print(‘該函數運行完畢‘)    return ‘這是test的傳回值‘res = test()        #實質調用的是wrapper函數print(res)
帶參數的裝飾器
import timedef timer(func):    def wrapper(*args,**kwargs):        startTime = time.time()        res = func(*args,**kwargs)        stopTime = time.time()        print(‘該函數已耗用時間為:%s‘ % (stopTime - startTime))        return res    return wrapper@timer  #test = timer(test)def test(name,age):    time.sleep(1)    print(‘該函數運行完畢,name is %s,age is %s‘ %(name,age))    return ‘這是test的傳回值‘res = test(‘andy‘,18)        #實質調用的是wrapper函數print(res)
補充知識:解壓序列
>>> a,b,c=(2,3,4)>>> a2>>> b3>>> c4

a , b, c變數要與元組中的元素一一對應才能取到值
那麼再看一個執行個體:

>>> l=[1,2,3,4,5,6,7,8]

利用序列的方法如何取得上面列表中的第一個元素與最後一個元素

>>> l=[1,2,3,4,5,6,7,8]>>> l[1, 2, 3, 4, 5, 6, 7, 8]>>> a,*_,c=l>>> a1>>> c8>>> a,*b,c=l>>> a1>>> b[2, 3, 4, 5, 6, 7]>>> c8

注意:號代表除a,c變數外所有元素,號後面必須要有一個變數,使用底線表示*號代表的變數不想被取出

該方法可用來交換兩個變數的值:

>>> a=1>>> b=2>>> a,b=(b,a)>>> a2>>> b1
裝飾器樣本
user_list = [    {‘name‘:‘andy‘,‘passwd‘:‘123‘},    {‘name‘:‘bruce‘,‘passwd‘:‘123‘},    {‘name‘:‘poe‘,‘passwd‘:‘123‘},    {‘name‘:‘jacky‘,‘passwd‘:‘123‘},]current_dic = {‘username‘:None,‘login‘:False}def auth_func(func):    def wrapper(*args,**kwargs):        if current_dic[‘username‘] and current_dic[‘login‘]:            res = func(*args,**kwargs)            return res        username = input(‘username:‘).strip()        password = input(‘password:‘).strip()        for user_dic in user_list:            if username == user_dic[‘name‘] and password == user_dic[‘passwd‘]:                current_dic[‘username‘] = username                current_dic[‘login‘] = True                res = func(*args,**kwargs)                return res        else:            print(‘使用者名稱或密碼錯誤‘)    return wrapper@auth_funcdef index():    print(‘歡迎來到JD首頁‘ )@auth_funcdef home(name):    print(‘welcome %s to home‘ % name)@auth_funcdef shopping(name):    print(‘%s的購物車裡有%s,%s,%s‘ %(name,‘奶茶‘,‘妹妹‘,‘牙膏‘))print(‘before : ‘,current_dic)index()home(‘andy‘)shopping(‘andy‘)print(‘after: ‘,current_dic)

代碼執行結果:

before :  {‘username‘: None, ‘login‘: False}username:andypassword:123歡迎來到JD首頁welcome andy to homeandy的購物車裡有奶茶,妹妹,牙膏after:  {‘username‘: ‘andy‘, ‘login‘: True}

python基礎四:裝飾器

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.