日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python中的装饰器decorator

發(fā)布時(shí)間:2025/3/20 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python中的装饰器decorator 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

python中的裝飾器

裝飾器是為了解決以下描述的問(wèn)題而產(chǎn)生的方法

我們?cè)谝延械暮瘮?shù)代碼的基礎(chǔ)上,想要?jiǎng)討B(tài)的為這個(gè)函數(shù)增加功能而又不改變?cè)瘮?shù)的代碼

例如有三個(gè)函數(shù):

def f1(x):return x def f2(x):return x*x def f3(x):return x*x*x

而我們想為這三個(gè)函數(shù)增加一個(gè)函數(shù)調(diào)用打印功能 類似print("call f1()")

如果我們直接修改的話,需要對(duì)每個(gè)函數(shù)的內(nèi)部進(jìn)行改寫。

所以為了簡(jiǎn)化代碼,我們可以使用python內(nèi)置的@裝飾器的方法,可以做到修飾函數(shù)的功能

Python的 decorator 本質(zhì)上就是一個(gè)高階函數(shù),它接收一個(gè)函數(shù)作為參數(shù),然后,返回一個(gè)新函數(shù)。

裝飾器可以極大地簡(jiǎn)化代碼,避免每個(gè)函數(shù)寫重復(fù)性代碼

不帶參數(shù)的decorator

例如我們可以編寫一個(gè)@log可以打印函數(shù)調(diào)用的裝飾器

def log(f):def fn(x):print ('call ' + f.__name__ + '()...')return f(x)return fn

然后我們可以測(cè)試一下

@log def f1(x):return xa=f1(1) print(a)

結(jié)果

call f1()... 1

但是,對(duì)于參數(shù)不是一個(gè)的函數(shù),調(diào)用將報(bào)錯(cuò):

''' 學(xué)習(xí)中遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' @log def add(x, y):return x + y print (add(1, 2))Traceback (most recent call last):File "D:/pythonwork/cvworktest/final/practice.py", line 12, in <module>print (add(1, 2)) TypeError: fn() takes 1 positional argument but 2 were given

這是因?yàn)閍dd() 函數(shù)需要傳入兩個(gè)參數(shù),但是 @log 寫死了只含一個(gè)參數(shù)的返回函數(shù)。

要讓 @log 自適應(yīng)任何參數(shù)定義的函數(shù),可以利用Python的*args 和**kw,保證任意個(gè)數(shù)的參數(shù)總是能正常調(diào)用:

def log(f):def fn(*args, **kw):print ('call ' + f.__name__ + '()...')return f(*args, **kw)return fn

現(xiàn)在,對(duì)于任意函數(shù),@log 都能正常工作。

帶參數(shù)decorator

上面的@log不帶任何參數(shù),同樣我們可以編寫一個(gè)帶參數(shù)的decorator

例如如果有的函數(shù)非常重要,希望打印出’[INFO] call xxx()…’,有的函數(shù)不太重要,希望打印出’[DEBUG] call xxx()…’,這時(shí)

log函數(shù)本身就需要傳入’INFO’或’DEBUG’這樣的參數(shù),類似這樣:

@log('DEBUG') def my_func():pass

我們把它翻譯成高階函數(shù)就是這樣:

my_func = log('DEBUG')(my_func)

展開(kāi):

log_decorator = log('DEBUG') my_func = log_decorator(my_func)

又相當(dāng)于:

''' 學(xué)習(xí)中遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' log_decorator = log('DEBUG') @log_decorator def my_func():pass

所以,帶參數(shù)的log函數(shù)首先返回一個(gè)decorator函數(shù),再讓這個(gè)decorator函數(shù)接收my_func并返回新函數(shù):

def log(content):def log_decorator(f):def fn(*args, **kw):print ('[%s] %s()...' % (content, f.__name__))return f(*args, **kw)return fnreturn log_decorator@log('DEBUG') def test():pass print (test())

結(jié)果:

[DEBUG] test()... None

decorator的注意事項(xiàng):

經(jīng)過(guò)@decorator“改造”后的函數(shù),和原函數(shù)相比,除了功能多一點(diǎn)外,還有很重要的一點(diǎn)就是函數(shù)自身的改變

在沒(méi)有decorator的情況下,打印函數(shù)名:

def f1(x):pass print (f1.__name__)

結(jié)果:

f1

有decorator的情況下,再打印函數(shù)名:

''' 學(xué)習(xí)中遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' def log(f):def wrapper(*args, **kw):print ('call...')return f(*args, **kw)return wrapper @log def f2(x):pass print (f2.__name__)

結(jié)果:

wrapper

由于decorator返回的新函數(shù)函數(shù)名已經(jīng)不是’f2’,而是@log內(nèi)部定義的’wrapper’。這對(duì)于那些依賴函數(shù)名的代碼就會(huì)失效。decorator還改變了函數(shù)的__doc__等其它屬性。如果要讓調(diào)用者看不出一個(gè)函數(shù)經(jīng)過(guò)了@decorator的“改造”,就需要把原函數(shù)的一些屬性復(fù)制到新函數(shù)中:

''' 學(xué)習(xí)中遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' def log(f):def wrapper(*args, **kw):print ('call...')return f(*args, **kw)wrapper.__name__ = f.__name__wrapper.__doc__ = f.__doc__return wrapper

這樣寫decorator很不方便,因?yàn)槲覀円埠茈y把原函數(shù)的所有必要屬性都一個(gè)一個(gè)復(fù)制到新函數(shù)上,所以Python內(nèi)置的functools可以用來(lái)自動(dòng)化完成這個(gè)“復(fù)制”的任務(wù):

import functools def log(f):@functools.wraps(f)def wrapper(*args, **kw):print ('call...')return f(*args, **kw)return wrapper

注意:對(duì)于函數(shù)的參數(shù)信息哦我們無(wú)法確定,因?yàn)檠b飾器與原函數(shù)的參數(shù)名不一定一樣

總結(jié)

以上是生活随笔為你收集整理的python中的装饰器decorator的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。