詳解python裝飾器
阿新 • • 發佈:2018-11-09
開放封閉原則的定義
開放封閉原則(OCP, Open CLosed Principle)是所有面向物件原則的核心。”需求總是變化的”,所以誕生出了這種原則,它主要體現在兩方面
- 對擴充套件開放,意味著有心得需求的時候,可以對現有的程式碼進行拓展,以適應新的情況
- 對修改封閉,意味著類一但設計完成,就可以獨立完成其工作,就不要對類進行任何的修改
裝飾器使用的場景
多用於插入日誌,效能測試,事務處理,快取,許可權校驗等場景。接下來我們以效能測試為例子
#這是裝飾器的常用寫法(被包裝的函式擁有引數和返回值的)
def wrapper(func):
#因為裝飾器是誰都可以使用的,我們無法確定任何函式的引數個數,所以我們用不定參
def inner(*args, **kwargs):
ret = func(*args, **kwargs)
return ret
return inner
@wrapper #相當於say = wrapper(say)
def say(something):
return something
say('hello')
假設我們有兩個函式f1和f2,他們都實現同一個功能。我們要比較兩者的效能誰更優,我們當然可以直接把測試函式test寫好,然後讓兩者內部呼叫,輸出結果。可是這不符合封閉開放原則,下面是裝飾器的寫法
import time
def wrapper(func):
def test():
print(func.__name__)
start_time = time.time()
func()
end_time = time.time()
print(end_time - start_time)
return test
@wrapper #相當與f1 = wrapper(f1)
def f1():
pass
@wrapper #相當於f2 = wrapper(f2)
def f2():
pass
f1()
f2()
高階一點的裝飾器
1. 帶有引數的裝飾器
def loggging(level):
def wrapper(func):
def inner(*args, **kwargs):
print('{level}: enter {func} function'.format(level=level,func=func.__name__))
ret = func(*args, **kwargs):
return ret
return inner
return wrapper
#相當於是先執行了logging()函式,返回了一個wrapper
@logging('INFO')
def say(something):
return something
2. 類裝飾器
在說類裝飾器之前,我們需要了解一個python的內建方法call(將例項變成可呼叫物件)
class Person():
def __call__(self):
print("hello world")
p = Person()
p() #hello world
類中裝飾器的常用寫法(其實就是用init來傳遞func,用call來呼叫)
class logging(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, *kwargs):
print(self.func.__name__)
retrun self.func(*args, **kwargs)
@logging
def say(something):
return something
總結
若是想使函式的功能得到拓展而又不修改函式的本身,那麼就使用裝飾器吧