【python學習筆記】Python裝飾器

leason-love發表於2017-09-18

裝飾器是什麼意思

一個大牛舉的例子:
內褲可以用來遮羞,但是到了冬天它沒法為我們防風禦寒,聰明的人們發明了長褲,有了長褲後寶寶再也不冷了,裝飾器就像我們這裡說的長褲,在不影響內褲作用的前提下,給我們的身子提供了保暖的功效。

裝飾器本質上是Python函式,可以為已存在的物件新增額外的功能,同時裝飾器還可以抽離出與函式無關的重用程式碼。具體應用場景如:插入日誌、效能測試、事務處理、快取、許可權校驗等。

舉個栗子

需要在某個原有功能上加一層驗證

def a():
    print 'a'

def b():
    print 'a'

a b 方法很多地方呼叫,不想更改原有呼叫方式

即:

def a():
    許可權驗證
    print 'a'

def b():
    許可權驗證
    print 'a'

假如有很多的介面—-

用裝飾器來實現:

def auth(func):
    def inner():
        # 驗證1
        return func()
    return inner

@auth
def a():
    print 'a'
@auth
def a():
    print 'b'

帶引數裝飾器

執行方法帶引數

def auth(func):
    def inner(arg1,arg2):
        # 驗證1
        return func(arg1,arg2)
    return inner

@auth
def a(arg1,arg2):
    print 'a'
@auth
def b(arg1,arg2):
    print 'b'

裝飾器帶引數

def auth(info):
    def decorator(func):
        def inner(arg1,arg2):
            # 驗證1
            print info
            return func(arg1,arg2)
        return inner
    return decorator



@auth(info='a')
def a(arg1,arg2):
    print 'a'
@auth(info='b')
def b(arg1,arg2):
    print 'b'

類裝飾器

再來看看類裝飾器,相比函式裝飾器,類裝飾器具有靈活度大、高內聚、封裝性等優點。使用類裝飾器還可以依靠類內部的__call__方法,當使用 @ 形式將裝飾器附加到函式上時,就會呼叫此方法。

class Foo(object):     
    def __init__(self, func):     
    self._func = func  
def __call__(self):     
    print ('class decorator runing')     
    self._func()    
    print ('class decorator ending')  
@Foo 
def bar():    
    print ('bar')  bar()

裝飾器執行順序

@a
@b
@c
def f ():

等於

f = a(b(c(f)))

帶來的問題(知乎劉志軍大牛)

使用裝飾器極大地複用了程式碼,但是他有一個缺點就是原函式的元資訊不見了,比如函式的docstring、name、引數列表

這個問題就比較嚴重的,好在我們有functools.wraps,wraps本身也是一個裝飾器,它能把原函式的元資訊拷貝到裝飾器函式中,這使得裝飾器函式也有和原函式一樣的元資訊了。

from functools import wraps 
def logged(func):     
    @wraps(func)     
    def with_logging(*args, **kwargs):         
        print func.__name__ + " was called"         
        return func(*args, **kwargs)     
    return with_logging 
@logged 
def f(x):     
    """does some math"""     
    return x + x * x  
print f.__name__  # prints 'f' 
print f.__doc__   # prints 'does some math'

leason | blog

相關文章