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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

装饰器的注意事项python_python中的装饰器decorator

發布時間:2024/9/27 python 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 装饰器的注意事项python_python中的装饰器decorator 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

python中的裝飾器

裝飾器是為了解決以下描述的問題而產生的方法

我們在已有的函數代碼的基礎上,想要動態的為這個函數增加功能而又不改變原函數的代碼

例如有三個函數:

deff1(x):returnxdeff2(x):return x*xdeff3(x):return x*x*x

而我們想為這三個函數增加一個函數調用打印功能 類似print("call f1()")

如果我們直接修改的話,需要對每個函數的內部進行改寫。

所以為了簡化代碼,我們可以使用python內置的@裝飾器的方法,可以做到修飾函數的功能

Python的?decorator?本質上就是一個高階函數,它接收一個函數作為參數,然后,返回一個新函數。

裝飾器可以極大地簡化代碼,避免每個函數寫重復性代碼

不帶參數的decorator

例如我們可以編寫一個@log可以打印函數調用的裝飾器

deflog(f):deffn(x):print ('call' + f.__name__ + '()...')returnf(x)return fn

然后我們可以測試一下

@logdeff1(x):returnx

a=f1(1)

print(a)

結果

call f1()...1

但是,對于參數不是一個的函數,調用將報錯:

@logdefadd(x, y):return x +yprint (add(1, 2))

Traceback (most recent call last):

File"D:/pythonwork/cvworktest/final/practice.py", line 12, in

print (add(1, 2))

TypeError: fn() takes1 positional argument but 2 were given

這是因為add()?函數需要傳入兩個參數,但是?@log?寫死了只含一個參數的返回函數。

要讓?@log?自適應任何參數定義的函數,可以利用Python的?*args?和?**kw,保證任意個數的參數總是能正常調用:

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

現在,對于任意函數,@log?都能正常工作。

帶參數decorator

上面的@log不帶任何參數,同樣我們可以編寫一個帶參數的decorator

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

log函數本身就需要傳入'INFO'或'DEBUG'這樣的參數,類似這樣:

@log('DEBUG')defmy_func():pass

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

my_func = log('DEBUG')(my_func)

展開:

log_decorator = log('DEBUG')

my_func= log_decorator(my_func)

又相當于:

log_decorator = log('DEBUG')

@log_decoratordefmy_func():pass

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

deflog(content):deflog_decorator(f):def fn(*args, **kw):print ('[%s] %s()...' % (content, f.__name__))return f(*args, **kw)returnfnreturnlog_decorator

@log('DEBUG')deftest():pass

print (test())

結果:

[DEBUG] test()...

None

decorator的注意事項:

經過@decorator“改造”后的函數,和原函數相比,除了功能多一點外,還有很重要的一點就是函數自身的改變

在沒有decorator的情況下,打印函數名:

deff1(x):pass

print (f1.__name__)

結果:

f1

有decorator的情況下,再打印函數名:

deflog(f):def wrapper(*args, **kw):print ('call...')return f(*args, **kw)returnwrapper

@logdeff2(x):pass

print (f2.__name__)

結果:

wrapper

由于decorator返回的新函數函數名已經不是'f2',而是@log內部定義的'wrapper'。這對于那些依賴函數名的代碼就會失效。decorator還改變了函數的__doc__等其它屬性。如果要讓調用者看不出一個函數經過了@decorator的“改造”,就需要把原函數的一些屬性復制到新函數中:

deflog(f):def wrapper(*args, **kw):print ('call...')return f(*args, **kw)

wrapper.__name__ = f.__name__wrapper.__doc__ = f.__doc__

return wrapper

這樣寫decorator很不方便,因為我們也很難把原函數的所有必要屬性都一個一個復制到新函數上,所以Python內置的functools可以用來自動化完成這個“復制”的任務:

importfunctoolsdeflog(f):

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

注意:對于函數的參數信息哦我們無法確定,因為裝飾器與原函數的參數名不一定一樣

總結

以上是生活随笔為你收集整理的装饰器的注意事项python_python中的装饰器decorator的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。