裝飾器

1.裝飾器定義和原則

定義:裝飾器本質是一個函數,(裝飾其它函數)就是爲其它函數添加附加功能。

原則:不能修改被裝飾函數的源代碼;不能修改被裝飾函數的調用方式。


2.實現裝飾器知識儲備

1.函數即變量

2.高階函數

a.把一個函數名當做實參傳給另一個函數--》可以實現不修改被裝飾函數的源代碼,爲其它函數添加附加功能

import time
def test1():
    time.sleep(3)
    print("this is test1")

def test2(func):
    start_time = time.time()
    func()
    stop_time = time.time()
    print("this func run time is %s"%(stop_time-start_time))
test2(test1)

b.返回值中包含函數名-->可以實現不修改被裝飾函數的調用方式

def test3():
    print("this is test3")

def test4(func):
    print("附加功能")
    return func
test3 = test4(test3)
test3()

注:調用函數的時候不加括號表示調用該函數內存地址如:print(test3)--><function test3 at 0x003E7660>,加括號表示執行該函數

3.嵌套函數 ,在一個函數裏再次聲明一個函數

def test5():
    print("this is test5")
    def test6():            #類似於局部變量,只能在局部調用
        print("this is test6")
    test6()
test5()

4.高階函數+嵌套函數--》裝飾器

a.裝飾器舉例1

import time
    #裝飾器:增加計算函數運行時間的功能
def timer(func):
    def deco(*args,**kwargs):                     #在裝飾器中增加*args,**kwargs之後,無論原函數參數的個數是多少,都可以適應
        start_time = time.time()
        res = func(*args,**kwargs)
        stop_time = time.time()
        print("this func run time is %s"%(stop_time-start_time))
        return res                               #在裝飾器中增加return res之後,可以返回原函數中的返回值
    return deco
#下面的1,2也就是裝飾器執行的過程

    #原函數
@timer                          #1、 @timer 實際上是在執行“test1 = timer(test1)”-->將原test1 內存地址傳給func,然後直接將deco的內存地址返回到test1
def test1():
    time.sleep(3)
    print("this is test1")
#test1 = timer(test1)
test1()                          #2、這時test1()相當於直接調用deco(*args,**kwargs),而deco裏的func還是指向的原test1的內存地址

@timer
def test2(name):
    time.sleep(1)
    print("this is %s"%(name))
test2("fengxiaoli")

@timer
def test3(name):
    time.sleep(2)
    print("this is %s"%(name))
    return "test3 res"
print(test3("cx"))      #先執行test3(cx),再打印test3的返回結果

b.裝飾器舉例2

#給網頁增加一個驗證的功能,並且home頁面用本地驗證,bbs頁面用ldap驗證
user = "fengxiaoli"
passwd = "123456"
def auth(auth_type):
    def out_wrapper(func):
        def wrapper(*args,**kwargs):
            if auth_type == "local":
                user_name = input("請輸入用戶名:").strip()
                password = input("請輸入密碼:").strip()
                if user_name == user and password == passwd:
                    res = func(*args,**kwargs)
                    print("welcome to home!")
                    return res
                else:
                    print("用戶名或密碼錯誤")
            else:
                print("ldap login")
        return wrapper
    return out_wrapper


#原函數
def index():
    print("this is index")

@auth(auth_type="local")                     #相對於裝飾器1中的例子,這裏調用裝飾器的時候使用了參數,在1中裝飾器不變得情況下直接在外在嵌套了一層函數,最外層函數接收的就是裝飾器中的參數
def home():
    print("this is home page")
home()

@auth(auth_type="ldap")
def bbs():
    print("this is bbs page")

bbs()


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章