1. 程式人生 > >詳解python裝飾器

詳解python裝飾器

開放封閉原則的定義

開放封閉原則(OCP, Open CLosed Principle)是所有面向物件原則的核心。”需求總是變化的”,所以誕生出了這種原則,它主要體現在兩方面

  1. 對擴充套件開放,意味著有心得需求的時候,可以對現有的程式碼進行拓展,以適應新的情況
  2. 對修改封閉,意味著類一但設計完成,就可以獨立完成其工作,就不要對類進行任何的修改

裝飾器使用的場景

多用於插入日誌,效能測試,事務處理,快取,許可權校驗等場景。接下來我們以效能測試為例子

#這是裝飾器的常用寫法(被包裝的函式擁有引數和返回值的)
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

總結

若是想使函式的功能得到拓展而又不修改函式的本身,那麼就使用裝飾器吧