溫馨提示×

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

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

python裝飾器帶參數(shù)的使用方式

發(fā)布時(shí)間:2020-04-28 09:50:09 來(lái)源:億速云 閱讀:311 作者:小新 欄目:編程語(yǔ)言

今天小編給大家分享的是python裝飾器帶參數(shù)的使用方式,相信很多人都不太了解,為了讓大家更加了解python裝飾器,所以給大家總結(jié)了以下內(nèi)容,一起往下看吧。一定會(huì)有所收獲的哦。

python裝飾器詳解

python裝飾器的詳細(xì)解析

什么是裝飾器?

python裝飾器(fuctional decorators)就是用于拓展原來(lái)函數(shù)功能的一種函數(shù),目的是在不改變?cè)瘮?shù)名(或類名)的情況下,給函數(shù)增加新的功能。

這個(gè)函數(shù)的特殊之處在于它的返回值也是一個(gè)函數(shù),這個(gè)函數(shù)是內(nèi)嵌“原“”函數(shù)的函數(shù)。

一般而言,我們要想拓展原來(lái)函數(shù)代碼,最直接的辦法就是侵入代碼里面修改,例如:

import time
def f():
    print("hello")
    time.sleep(1)
    print("world")  

這是我們最原始的的一個(gè)函數(shù),然后我們?cè)噲D記錄下這個(gè)函數(shù)執(zhí)行的總時(shí)間,那最簡(jiǎn)單的做法就是改動(dòng)原來(lái)的代碼:

import time
def f():
    start_time = time.time()
    print("hello")
    time.sleep(1)
    print("world")
    end_time = time.time()
    execution_time = (end_time - start_time)*1000
    print("time is %d ms" %execution_time)

但是實(shí)際工作中,有些時(shí)候核心代碼并不可以直接去改,所以在不改動(dòng)原代碼的情況下,我們可以再定義一個(gè)函數(shù)。(但是生效需要再次執(zhí)行函數(shù))

import time
def deco(func):
    start_time = time.time()
    f()
    end_time = time.time()
    execution_time = (end_time - start_time)*1000
    print("time is %d ms" %execution_time)
def f():
    print("hello")
    time.sleep(1)
    print("world")
if __name__ == '__main__':
    deco(f)
    print("f.__name__ is",f.__name__)
    print()

這里我們定義了一個(gè)函數(shù)deco,它的參數(shù)是一個(gè)函數(shù),然后給這個(gè)函數(shù)嵌入了計(jì)時(shí)功能。但是想要拓展這一千萬(wàn)個(gè)函數(shù)功能,

就是要執(zhí)行一千萬(wàn)次deco()函數(shù),所以這樣并不理想!接下來(lái),我們可以試著用裝飾器來(lái)實(shí)現(xiàn),先看看裝飾器最原始的面貌。

import time
def deco(f):
    def wrapper():
        start_time = time.time()
        f()
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" %execution_time )
    return wrapper
@deco
def f():
    print("hello")
    time.sleep(1)
    print("world")
if __name__ == '__main__':
    f()

這里的deco函數(shù)就是最原始的裝飾器,它的參數(shù)是一個(gè)函數(shù),然后返回值也是一個(gè)函數(shù)。

其中作為參數(shù)的這個(gè)函數(shù)f()就在返回函數(shù)wrapper()的內(nèi)部執(zhí)行。然后在函數(shù)f()前面加上@deco,

f()函數(shù)就相當(dāng)于被注入了計(jì)時(shí)功能,現(xiàn)在只要調(diào)用f(),它就已經(jīng)變身為“新的功能更多”的函數(shù)了,

(不需要重復(fù)執(zhí)行原函數(shù))。

擴(kuò)展1:帶有固定參數(shù)的裝飾器

import time
def deco(f):
    def wrapper(a,b):
        start_time = time.time()
        f(a,b)
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" % execution_time)
    return wrapper
@deco
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
if __name__ == '__main__':
    f(3,4)

擴(kuò)展2:無(wú)固定參數(shù)的裝飾器

import time
def deco(f):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        execution_time_ = (end_time - start_time)*1000
        print("time is %d ms" %execution_time)
    return wrapper
@deco
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
@deco
def f2(a,b,c):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b+c))
if __name__ == '__main__':
    f2(3,4,5)
    f(3,4)

擴(kuò)展3:使用多個(gè)裝飾器,裝飾一個(gè)函數(shù)

import time
def deco01(f):
    def wrapper(*args, **kwargs):
        print("this is deco01")
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" % execution_time)
        print("deco01 end here")
    return wrapper
def deco02(f):
    def wrapper(*args, **kwargs):
        print("this is deco02")
        f(*args, **kwargs)
        print("deco02 end here")
    return wrapper
@deco01
@deco02
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
if __name__ == '__main__':
    f(3,4)
'''
this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1003 ms
deco01 end here
'''

裝飾器調(diào)用順序

裝飾器是可以疊加使用的,那么使用裝飾器以后代碼是啥順序呢?

對(duì)于Python中的”@”語(yǔ)法糖,裝飾器的調(diào)用順序與使用 @ 語(yǔ)法糖聲明的順序相反。

在這個(gè)例子中,”f(3, 4) = deco01(deco02(f(3, 4)))”。

Python內(nèi)置裝飾器

在Python中有三個(gè)內(nèi)置的裝飾器,都是跟class相關(guān)的:staticmethod、classmethod 和property。

staticmethod 是類靜態(tài)方法,其跟成員方法的區(qū)別是沒(méi)有 self 參數(shù),并且可以在類不進(jìn)行實(shí)例化的情況下調(diào)用

classmethod 與成員方法的區(qū)別在于所接收的第一個(gè)參數(shù)不是 self (類實(shí)例的指針),而是cls(當(dāng)前類的具體類型)

property 是屬性的意思,表示可以通過(guò)通過(guò)類實(shí)例直接訪問(wèn)的信息

對(duì)于staticmethod和classmethod這里就不介紹了,通過(guò)一個(gè)例子看看property。

python裝飾器帶參數(shù)的使用方式

注意,對(duì)于Python新式類(new-style class),如果將上面的 “@var.setter” 裝飾器所裝飾的成員函數(shù)去掉,則Foo.var 屬性為只讀屬性,使用 “foo.var = ‘var 2′” 進(jìn)行賦值時(shí)會(huì)拋出異常。但是,對(duì)于Python classic class,所聲明的屬性不是 read-only的,所以即使去掉”@var.setter”裝飾器也不會(huì)報(bào)錯(cuò)。

總結(jié)

本文介紹了Python裝飾器的一些使用,裝飾器的代碼還是比較容易理解的。只要通過(guò)一些例子進(jìn)行實(shí)際操作一下,就很容易理解了。

關(guān)于python裝飾器帶參數(shù)的使用方式就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的參考價(jià)值,可以學(xué)以致用。如果喜歡本篇文章,不妨把它分享出去讓更多的人看到。

向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