溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

python基礎(chǔ)四:裝飾器

發(fā)布時(shí)間:2020-08-10 13:53:42 來(lái)源:網(wǎng)絡(luò) 閱讀:363 作者:琴酒網(wǎng)絡(luò) 欄目:編程語(yǔ)言

裝飾器本質(zhì):就是函數(shù),功能是為其他函數(shù)添加附加功能

裝飾器原則:

  1. 不修改被修飾函數(shù)的源代碼
  2. 不修改修飾函數(shù)的調(diào)用方式

裝飾器的知識(shí)儲(chǔ)備:

裝飾器 = 高階函數(shù) + 函數(shù)嵌套 + 閉包

初識(shí)裝飾器

先看一個(gè)需求:下面這個(gè)函數(shù)用來(lái)計(jì)算1到20的和

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

但現(xiàn)在需求有變,不僅要計(jì)算1到20的和,還需要計(jì)算該函數(shù)運(yùn)行的時(shí)間,此時(shí)裝飾器就應(yīng)需而生

import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        stop_time = time.time()
        print('函數(shù)運(yùn)行的時(shí)間為:%s' % (stop_time - start_time))
        return res
    return wrapper
@timer
def calc(l):
    res = 0
    for i in l:
        time.sleep(0.01)
        res += i
    return res
result = calc(range(1,21))
print(result)

運(yùn)行結(jié)果如下:

函數(shù)運(yùn)行的時(shí)間為:0.2048475742340088
210

上面的timer函數(shù)就是calc函數(shù)的裝飾器

高階函數(shù)

高階函數(shù)定義:
1.函數(shù)接收的參數(shù)是一個(gè)函數(shù)名

2.函數(shù)的返回值是一個(gè)函數(shù)名

3.滿足上述條件任意一個(gè),都可稱之為高階函數(shù)

高階函數(shù)示例

def foo():
    print('我的函數(shù)名作為參數(shù)傳給高階函數(shù)')
def gao_jie1(func):
    print('我就是高階函數(shù)1,我接收的參數(shù)名是%s' %func)
    func()

def gao_jie2(func):
    print('我就是高階函數(shù)2,我的返回值是%s' %func)
    return func

gao_jie1(foo)
gao_jie2(foo)

把函數(shù)當(dāng)作參數(shù)傳給高階函數(shù)

#高階函數(shù)應(yīng)用1:把函數(shù)當(dāng)做參數(shù)傳給高階函數(shù)
import time
def foo():
    print('from the foo')

def timmer(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print('函數(shù)%s 運(yùn)行時(shí)間是%s' %(func,stop_time-start_time))
timmer(foo)
#總結(jié):我們確實(shí)為函數(shù)foo增加了foo運(yùn)行時(shí)間的功能,但是foo原來(lái)的執(zhí)行方式是foo(),現(xiàn)在我們需要調(diào)用高階函數(shù)timmer(foo),改變了函數(shù)的調(diào)用方式

函數(shù)返回值是函數(shù)名

#高階函數(shù)應(yīng)用2:把函數(shù)名當(dāng)做參數(shù)傳給高階函數(shù),高階函數(shù)直接返回函數(shù)名
import time
def foo():
    print('from the foo')

def timmer(func):
    start_time=time.time()
    return func
    stop_time=time.time()
    print('函數(shù)%s 運(yùn)行時(shí)間是%s' %(func,stop_time-start_time))
foo=timmer(foo)
foo()
#總結(jié):我們確實(shí)沒(méi)有改變foo的調(diào)用方式,但是我們也沒(méi)有為foo增加任何新功能

高階函數(shù)總結(jié)
1.函數(shù)接收的參數(shù)是一個(gè)函數(shù)名
  作用:在不修改函數(shù)源代碼的前提下,為函數(shù)添加新功能,
  不足:會(huì)改變函數(shù)的調(diào)用方式
2.函數(shù)的返回值是一個(gè)函數(shù)名
  作用:不修改函數(shù)的調(diào)用方式
  不足:不能添加新功能

函數(shù)嵌套

def father(name):
    print('from father %s' %name)
    def son():
        print('from son')
        def grandson():
            print('from grandson')
        grandson()
    son()
father('Poe')

閉包

'''
閉包:在一個(gè)作用哉里放放定義變量,相當(dāng)于打了一個(gè)包
'''
def father(name):
    def son():
        print('My father is %s' %name)
        def grandson():
            print('my grandpa is %s' %name)
        grandson()
    son()
father('Poe')

無(wú)參數(shù)裝飾器

無(wú)參裝飾器=高級(jí)函數(shù)+函數(shù)嵌套

基本框架

'''
這就是一個(gè)實(shí)現(xiàn) 裝飾器最基本的架子
'''
def timer(func):
    def wrapper():
        func()
    return wrapper()

回到上面需要計(jì)算函數(shù)運(yùn)行時(shí)間的需求,在不使用裝飾器的情況下加上以下代碼

import time
def timer(func):
    def wrapper():
        startTime = time.time()
        func()
        stopTime = time.time()
        print('函數(shù)運(yùn)行時(shí)間為:%s' % (stopTime - startTime))
    return wrapper

def test():
    time.sleep(3)
    print('test函數(shù)運(yùn)行完畢')

res = timer(test)
res()

使用裝飾器

import time
def timer(func):
    def wrapper():
        startTime = time.time()
        func()
        stopTime = time.time()
        print('函數(shù)運(yùn)行時(shí)間為:%s' % (stopTime - startTime))
    return wrapper
@timer  #相當(dāng)于test = timer(test)
def test():
    time.sleep(3)
    print('test函數(shù)運(yùn)行完畢')
test()

返回值問(wèn)題
如果test函數(shù)中有返回值怎么返回呢?test函數(shù)被調(diào)用時(shí),實(shí)質(zhì)就是調(diào)用wrapper函數(shù),如果要返回test函數(shù)中的值,必須要在wrapper函數(shù)中將該值返回

import time

def timer(func):
    def wrapper():
        startTime = time.time()
        res = func()
        stopTime = time.time()
        print('該函數(shù)運(yùn)行時(shí)間為:%s' % (stopTime - startTime))
        return res
    return wrapper

@timer
def test():
    time.sleep(1)
    print('該函數(shù)運(yùn)行完畢')
    return '這是test的返回值'
res = test()        #實(shí)質(zhì)調(diào)用的是wrapper函數(shù)
print(res)

帶參數(shù)的裝飾器

import time

def timer(func):
    def wrapper(*args,**kwargs):
        startTime = time.time()
        res = func(*args,**kwargs)
        stopTime = time.time()
        print('該函數(shù)運(yùn)行時(shí)間為:%s' % (stopTime - startTime))
        return res
    return wrapper

@timer  #test = timer(test)
def test(name,age):
    time.sleep(1)
    print('該函數(shù)運(yùn)行完畢,name is %s,age is %s' %(name,age))
    return '這是test的返回值'
res = test('andy',18)        #實(shí)質(zhì)調(diào)用的是wrapper函數(shù)
print(res)

補(bǔ)充知識(shí):解壓序列

>>> a,b,c=(2,3,4)
>>> a
2
>>> b
3
>>> c
4

a , b, c變量要與元組中的元素一一對(duì)應(yīng)才能取到值
那么再看一個(gè)實(shí)例:

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

利用序列的方法如何取得上面列表中的第一個(gè)元素與最后一個(gè)元素

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

注意:號(hào)代表除a,c變量外所有元素,號(hào)后面必須要有一個(gè)變量,使用下劃線表示*號(hào)代表的變量不想被取出

該方法可用來(lái)交換兩個(gè)變量的值:

>>> a=1
>>> b=2
>>> a,b=(b,a)
>>> a
2
>>> b
1

裝飾器示例

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('用戶名或密碼錯(cuò)誤')
    return wrapper

@auth_func
def index():
    print('歡迎來(lái)到JD主頁(yè)' )
@auth_func
def home(name):
    print('welcome %s to home' % name)
@auth_func
def shopping(name):
    print('%s的購(gòu)物車?yán)镉?s,%s,%s' %(name,'奶茶','妹妹','牙膏'))

print('before : ',current_dic)
index()
home('andy')
shopping('andy')
print('after: ',current_dic)

代碼執(zhí)行結(jié)果:

before :  {'username': None, 'login': False}
username:andy
password:123
歡迎來(lái)到JD主頁(yè)
welcome andy to home
andy的購(gòu)物車?yán)镉心滩?妹妹,牙膏
after:  {'username': 'andy', 'login': True}
向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI