Python-00裝飾器
裝飾器
[toc]
TODO
總結(jié)
裝飾器的作用就是為已經(jīng)存在的函數(shù)或?qū)ο筇砑宇~外的功能
裝飾器使用種類:
- 函數(shù)裝飾器
- 類裝飾器
- 函數(shù)裝飾器裝飾 類
- 類裝飾器裝飾 函數(shù)
裝飾器樣例
@staticmethod
@logging
def a():
return 1
pass
等價于
a = staticmethod(logging(a))
默認(rèn)裝飾器函數(shù)
-
@property
通過property裝飾器控制類的屬性的綁定與獲取,一般就是給某個屬性增加一個驗證類型等功能。 -
@staticmethod
將被裝飾的函數(shù)從類中分離出來,該函數(shù)不能訪問類的屬性,簡單說可以將該函數(shù)理解為一個獨立的函數(shù),不允許使用self。
staticmethod 就是將該被裝飾的函數(shù)與該類沒有關(guān)系,該函數(shù)不能用self傳參,需要和普通函數(shù)一樣傳參。 -
@classmethod
classmethod 可以用來為一個類創(chuàng)建一些預(yù)處理的實例.類方法只能找類變量,不能訪問實例變量
裝飾器庫 functools
因為使用裝飾器 functools 會導(dǎo)致函數(shù)或類信息缺失。
例如 func.__name__
所以需要使用 functools 裝飾器庫處理
使用方法:
每個裝飾器前面加上下句話即可
@functools.wraps(func)
樣例如下所示:
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print '%s %s():' % (text, func.__name__)
return func(*args, **kw)
return wrapper
return decorator
裝飾器&函數(shù)
函數(shù)簡單說明
參考鏈接: 12步輕松搞定python裝飾器
了解裝飾器之前也需要了解內(nèi)部函數(shù)與函數(shù)閉包。
參考鏈接: 內(nèi)部函數(shù)&函數(shù)閉包
內(nèi)部函數(shù)
def wai_hanshu(canshu_1):
def nei_hanshu(canshu_2): # 我在函數(shù)內(nèi)部有定義了一個函數(shù)
return canshu_1*canshu_2
return nei_hanshu # 我將內(nèi)部函數(shù)返回出去
a = wai_hanshu(123) # 此時 canshu_1 = 123
print a
print a(321) # canshu_2 = 321
閉包說明
參考鏈接: 函數(shù)閉包
python中的閉包從表現(xiàn)形式上定義(解釋)為:
如果在一個內(nèi)部函數(shù)里,對在外部作用域(但不是在全局作用域)的變量進行引用,那么內(nèi)部函數(shù)就被認(rèn)為是閉包(closure)。
- 閉包=函數(shù)+引用環(huán)境
- 閉包中是不能修改外部作用域的局部變量的
- 當(dāng)閉包執(zhí)行完后,仍然能夠保持住當(dāng)前的運行環(huán)境
- 閉包可以根據(jù)外部作用域的局部變量來得到不同的結(jié)果
裝飾器說明
裝飾器本質(zhì)上是一個Python函數(shù),它可以讓其他函數(shù)在不需要做任何代碼變動的前提下增加額外功能。
裝飾器的返回值也是一個函數(shù)對象。
它經(jīng)常用于有切面需求的場景,比如:插入日志、性能測試、事務(wù)處理、緩存、權(quán)限校驗等場景。
裝飾器是解決這類問題的絕佳設(shè)計,有了裝飾器,我們就可以抽離出大量與函數(shù)功能本身無關(guān)的雷同代碼并繼續(xù)重用。
裝飾器的作用就是為已經(jīng)存在的函數(shù)或?qū)ο筇砑宇~外的功能
裝飾器/修飾符 - decorator
裝飾器知識
函數(shù)裝飾器
參考鏈接:
https://www.cnblogs.com/cicaday/p/python-decorator.html
概括的講,裝飾器的作用就是為已經(jīng)存在的函數(shù)或?qū)ο筇砑宇~外的功能
簡單裝飾器樣例
def debug(func):
def wrapper(*args, **kwargs): # 指定宇宙無敵參數(shù)
print "[DEBUG]: enter {}()".format(func.__name__)
print 'Prepare and say...',
return func(*args, **kwargs)
return wrapper # 返回
@debug
def say(something):
print "hello {}!".format(something)
等同于
say = debug(say)
原理分析
@decorator_a
def f():
pass
等價于
f = decorator_a(f)
裝飾器滿足的條件
- 裝飾器函數(shù)運行在函數(shù)定義的時候
- 裝飾器需要返回一個可執(zhí)行的對象
- 裝飾器返回的可執(zhí)行對象要兼容函數(shù)f的參數(shù)
類裝飾器
類裝飾器中必須使用 __call__ 方法。將類實例轉(zhuǎn)為可調(diào)用對象。
class Decorator(object):
def __init__(self, f):
self.f = f
def __call__(self):
print("decorator start")
self.f()
print("decorator end")
@Decorator
def func():
print("func")
func()
這里有注意的是:call()是一個特殊方法,它可將一個類實例變成一個可調(diào)用對象:
p = Decorator(func) # p是類Decorator的一個實例
p() # 實現(xiàn)了__call__()方法后,p可以被調(diào)用
要使用類裝飾器必須實現(xiàn)類中的call()方法,就相當(dāng)于將實例變成了一個方法。
裝飾器鏈
所謂裝飾器鏈,即多個裝飾器的解析方式。
@decorator_b
@decorator_a
def test():
pass
等同于
test = decorator_b(decorator_a(test))
裝飾器執(zhí)行順序 是從近到遠依次執(zhí)行。
內(nèi)置裝飾器
內(nèi)置裝飾器
- 特性(property)
- 靜態(tài)方法(staticmethod)
- 類方法(classmethod)
附錄A-裝飾器庫參數(shù)表
functools,用于高階函數(shù):
指那些作用于函數(shù)或者返回其它函數(shù)的函數(shù),通常只要是可以被當(dāng)做函數(shù)調(diào)用的對象就是這個模塊的目標(biāo)。
functools方法
- cmp_to_key,將一個比較函數(shù)轉(zhuǎn)換關(guān)鍵字函數(shù);
- partial,針對函數(shù)起作用,并且是部分的;
- reduce,與python內(nèi)置的reduce函數(shù)功能一樣;
- total_ordering,在類裝飾器中按照缺失順序,填充方法;
- update_wrapper,更新一個包裹(wrapper)函數(shù),使其看起來更像被包裹(wrapped)的函數(shù);
- wraps,可用作一個裝飾器,簡化調(diào)用update_wrapper的過程;
cmp_to_key
將老式的比較函數(shù)(comparison function)轉(zhuǎn)換為關(guān)鍵字函數(shù)(key function),與接受key function的工具一同使用(例如sorted,min,max,heapq.nlargest,itertools.groupby),該函數(shù)主要用于將程序轉(zhuǎn)換成Python 3格式的,因為Python 3中不支持比較函數(shù)。比較函數(shù)是可調(diào)用的,接受兩個參數(shù),比較這兩個參數(shù)并根據(jù)他們的大小關(guān)系返回負值、零或者正值中的一個。關(guān)鍵字函數(shù)也是可調(diào)用的,接受一個參數(shù),同時返回一個可以用作排序關(guān)鍵字的值。
partial
functools.partial(func, *args, **keywords),函數(shù)裝飾器,返回一個新的partial對象。調(diào)用partial對象和調(diào)用被修飾的函數(shù)func相同,只不過調(diào)用partial對象時傳入的參數(shù)個數(shù)通常要少于調(diào)用func時傳入的參數(shù)個數(shù)。
reduce
與Python內(nèi)置的reduce函數(shù)一樣,為了向Python3過渡
total_ordering
這是一個類裝飾器,給定一個類,這個類定義了一個或者多個比較排序方法,這個類裝飾器將會補充其余的比較方法,減少了自己定義所有比較方法時的工作量.
被修飾的類必須至少定義 lt(), le(),gt(),ge()中的一個,同時,被修飾的類還應(yīng)該提供 eq()方法。
update_wrapper
更新一個包裹(wrapper)函數(shù),使其看起來更像被包裹(wrapped)的函數(shù)。
wraps
這個函數(shù)可用作一個裝飾器,簡化調(diào)用update_wrapper的過程,調(diào)用這個函數(shù)等價于調(diào)用partial(update_wrapper, wrapped = wrapped, assigned = assigned,updated = updated)。
附錄B-測試代碼樣例
文件: /home/scfan/pro/server/pro/tools/base_decorator.py
import time
import datetime
import functools
def decorator_func(text="all"):
u""" 統(tǒng)計函數(shù)相關(guān)信息 All
- 函數(shù)運行時間
- 函數(shù)名稱
"""
def decorator(func,*args,**kwargs):
@functools.wraps(func)
def wrapper(*args,**kwargs):
start = datetime.datetime.now()
data = func(*args, **kwargs)
runtime = datetime.datetime.now() - start
msg = "@函數(shù)運行信息: 函數(shù)類型[%s],函數(shù)名稱[%s],運行時間[%s秒]"%(text,func.__name__,runtime.total_seconds())
print(msg)
return data
return wrapper
return decorator
class Decorator(object):
u"""
裝飾器類
"""
def __init__(self, func):
self.func = func
# __call__()是一個特殊方法,它可將一個類實例變成一個可調(diào)用對象
def __call__(self, *args, **kwargs):
print("decorator start")
self.func()
print("decorator end")
if __name__ == '__main__':
@Decorator
@decorator_func("all")
def a(b="cc"):
for i in range(2):
time.sleep(1)
print "函數(shù)運行...."
return b
a()
運行信息
(env) [scfan@WOM tools]$ python base_decorator.py
decorator start
函數(shù)運行....
@函數(shù)運行信息: 函數(shù)類型[all],函數(shù)名稱[a],運行時間[2.004331秒]
decorator end