1. 程式人生 > >python3之裝飾器(類裝飾器)實現 下篇

python3之裝飾器(類裝飾器)實現 下篇

上篇中我們介紹了閉包的用法,同時利用裝飾器實現了為函式新增返回原始資料的功能,那麼它怎麼實現的呢,讓我們揭開它神祕的面紗。

def decorator(f):
    def wrapper(x,y):
        print("引數1為:%s,引數2為:%s"%(x,y))
        return f(x,y)
    return wrapper
    
@decorator
def add(x,y):
    return x+y

print(add(2,3))

解析:**本質上裝飾器就是一個返回函式的高階函式,它接收一個函式,並返回一個函式,用法就是在被裝飾的函式上面加上@裝飾器函式名。**此時,把@decorator 放到add函式的定義處,相當於執行了 add = decorator(add),結果就是返回了一個函式物件wrapper,wrapper後加上(x,y),然後執行裝飾器函式內部定義的wrapper()函式。此時函式的指向發生了變化,讓我們看下面的程式碼:

def decorator(f):
    def wrapper(x,y):
        print("引數1為:%s,引數2為:%s"%(x,y),f.__name__)
        return f(x,y)
    return wrapper

@decorator
def add(x,y):
    print(add.__name__)
    return x+y

print(add(2,3))

執行結果:

引數1為:2,引數2為:3 add
wrapper
5

解析:**在add函式前加上@decorator,執行了decorator(add)函式,add代表傳入的形參f,返回的wrapper指向了原有的add位置,新的add函式名字發生了改變。**所以,我們可以使用python的functools模組把原始函式的__name__等屬性複製到wrapper()函式中,否則,有些依賴函式簽名的程式碼執行就會出錯。在這之上我們還可以再新增一個函式,輸出一些引數。

import functools

def log(text):
    def decorator(f):
        @functools.wraps(f)
        def wrapper(x,y):
            print(text,"引數1為:%s,引數2為:%s"%(x,y),f.__name__)
            return f(x,y)
        return wrapper
    return decorator

@log("python之裝飾器")
def add(x,y):
    print(add.__name__)
    return x+y

print(add(2,3))

執行結果:

python之裝飾器 引數1為:2,引數2為:3 add
add
5

解析:加上@functools.wraps(f)後,新的add()函式的名字還是原來的add,我們添加了log函式,傳入了一串字元,函式執行時可以打印出來。

總結:裝飾器能夠將一個函式的功能在不修改程式碼的情況下進行擴充套件,在函式定義的上方@裝飾器函式名 即可直接使用裝飾器對下面的函式進行裝飾。

類裝飾器 接下來我們用面對物件的方法實現裝飾器的功能,你應該有python面對物件程式設計的基礎,這裡面會用到魔法方法。 <1>

class Decrator(object):

    def __init__(self,fn):
        print("初始化函式",fn.__name__)
        self._func = fn

    def __call__(self,*args):
        print("列印的內容",*args)
        return self._func(*args)

@Decrator
def sum(x,y):
    print(sum)
    return x+y

print(sum(3,3))

執行結果

初始化函式 sum
列印的內容 3 3
<__main__.Decrator object at 0x0000024986FF7198>
6

解析:函式sum定義前加上@Decorator,相當於例項化類物件Decorator(sum),同時初始化例項屬性self._func=sum函式;接下來例項物件後加上(),會呼叫例項物件的__call__方法,打印出內容和引數,然後返回例項屬性即sum函式並執行函式計算x+y。