Python-00裝飾器
裝飾器
文章目錄
TODO
總結
裝飾器的作用就是爲已經存在的函數或對象添加額外的功能
裝飾器使用種類:
- 函數裝飾器
- 類裝飾器
- 函數裝飾器裝飾 類
- 類裝飾器裝飾 函數
裝飾器樣例
@staticmethod
@logging
def a():
return 1
pass
等價於
a = staticmethod(logging(a))
默認裝飾器函數
- @property
通過property裝飾器控制類的屬性的綁定與獲取,一般就是給某個屬性增加一個驗證類型等功能。 - @staticmethod
將被裝飾的函數從類中分離出來,該函數不能訪問類的屬性,簡單說可以將該函數理解爲一個獨立的函數,不允許使用self。
staticmethod 就是將該被裝飾的函數與該類沒有關係,該函數不能用self傳參,需要和普通函數一樣傳參。 - @classmethod
classmethod 可以用來爲一個類創建一些預處理的實例.類方法只能找類變量,不能訪問實例變量
裝飾器庫 functools
因爲使用裝飾器 functools 會導致函數或類信息缺失。
例如 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
裝飾器&函數
函數簡單說明
參考鏈接: 12步輕鬆搞定python裝飾器
瞭解裝飾器之前也需要了解內部函數與函數閉包。
參考鏈接: 內部函數&函數閉包
內部函數
def wai_hanshu(canshu_1):
def nei_hanshu(canshu_2): # 我在函數內部有定義了一個函數
return canshu_1*canshu_2
return nei_hanshu # 我將內部函數返回出去
a = wai_hanshu(123) # 此時 canshu_1 = 123
print a
print a(321) # canshu_2 = 321
閉包說明
參考鏈接: 函數閉包
python中的閉包從表現形式上定義(解釋)爲:
如果在一個內部函數裏,對在外部作用域(但不是在全局作用域)的變量進行引用,那麼內部函數就被認爲是閉包(closure)。
- 閉包=函數+引用環境
- 閉包中是不能修改外部作用域的局部變量的
- 當閉包執行完後,仍然能夠保持住當前的運行環境
- 閉包可以根據外部作用域的局部變量來得到不同的結果
裝飾器說明
裝飾器本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能。
裝飾器的返回值也是一個函數對象。
它經常用於有切面需求的場景,比如:插入日誌、性能測試、事務處理、緩存、權限校驗等場景。
裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量與函數功能本身無關的雷同代碼並繼續重用。
裝飾器的作用就是爲已經存在的函數或對象添加額外的功能
裝飾器/修飾符 - decorator
裝飾器知識
函數裝飾器
參考鏈接:
https://www.cnblogs.com/cicaday/p/python-decorator.html
概括的講,裝飾器的作用就是爲已經存在的函數或對象添加額外的功能
簡單裝飾器樣例
def debug(func):
def wrapper(*args, **kwargs): # 指定宇宙無敵參數
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)
裝飾器滿足的條件
- 裝飾器函數運行在函數定義的時候
- 裝飾器需要返回一個可執行的對象
- 裝飾器返回的可執行對象要兼容函數f的參數
類裝飾器
類裝飾器中必須使用 __call__ 方法。將類實例轉爲可調用對象。
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()是一個特殊方法,它可將一個類實例變成一個可調用對象:
p = Decorator(func) # p是類Decorator的一個實例
p() # 實現了__call__()方法後,p可以被調用
要使用類裝飾器必須實現類中的__call__()方法,就相當於將實例變成了一個方法。
裝飾器鏈
所謂裝飾器鏈,即多個裝飾器的解析方式。
@decorator_b
@decorator_a
def test():
pass
等同於
test = decorator_b(decorator_a(test))
裝飾器執行順序 是從近到遠依次執行。
內置裝飾器
內置裝飾器
- 特性(property)
- 靜態方法(staticmethod)
- 類方法(classmethod)
附錄A-裝飾器庫參數表
functools,用於高階函數:
指那些作用於函數或者返回其它函數的函數,通常只要是可以被當做函數調用的對象就是這個模塊的目標。
functools方法
- cmp_to_key,將一個比較函數轉換關鍵字函數;
- partial,針對函數起作用,並且是部分的;
- reduce,與python內置的reduce函數功能一樣;
- total_ordering,在類裝飾器中按照缺失順序,填充方法;
- update_wrapper,更新一個包裹(wrapper)函數,使其看起來更像被包裹(wrapped)的函數;
- wraps,可用作一個裝飾器,簡化調用update_wrapper的過程;
cmp_to_key
將老式的比較函數(comparison function)轉換爲關鍵字函數(key function),與接受key function的工具一同使用(例如sorted,min,max,heapq.nlargest,itertools.groupby),該函數主要用於將程序轉換成Python 3格式的,因爲Python 3中不支持比較函數。比較函數是可調用的,接受兩個參數,比較這兩個參數並根據他們的大小關係返回負值、零或者正值中的一個。關鍵字函數也是可調用的,接受一個參數,同時返回一個可以用作排序關鍵字的值。
partial
functools.partial(func, *args, **keywords),函數裝飾器,返回一個新的partial對象。調用partial對象和調用被修飾的函數func相同,只不過調用partial對象時傳入的參數個數通常要少於調用func時傳入的參數個數。
reduce
與Python內置的reduce函數一樣,爲了向Python3過渡
total_ordering
這是一個類裝飾器,給定一個類,這個類定義了一個或者多個比較排序方法,這個類裝飾器將會補充其餘的比較方法,減少了自己定義所有比較方法時的工作量.
被修飾的類必須至少定義 lt(), le(),gt(),ge()中的一個,同時,被修飾的類還應該提供 eq()方法。
update_wrapper
更新一個包裹(wrapper)函數,使其看起來更像被包裹(wrapped)的函數。
wraps
這個函數可用作一個裝飾器,簡化調用update_wrapper的過程,調用這個函數等價於調用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""" 統計函數相關信息 All
- 函數運行時間
- 函數名稱
"""
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 = "@函數運行信息: 函數類型[%s],函數名稱[%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__()是一個特殊方法,它可將一個類實例變成一個可調用對象
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 "函數運行...."
return b
a()
運行信息
(env) [scfan@WOM tools]$ python base_decorator.py
decorator start
函數運行....
@函數運行信息: 函數類型[all],函數名稱[a],運行時間[2.004331秒]
decorator end