Python學習之路基礎篇--11-12Python基礎,函數的裝飾器

  對於裝飾器來講,就是在不改變函數的調用的狀況下,對函數的先後增長了些許功能,這徹底符合函數的 開放封閉 原則。裝飾器的本質 其實就是一個閉包函數。閉包

  這是一個裝飾器的步驟圖app

def wrapper(func):  # 2
    def inner(*args,**kwargs):  # 5
        ret = func(*args,**kwargs)  # 6
        return ret  #10
    return inner   # 3

@wrapper  #shopping = wrappers(shooping)   # 1 --shopping = innner
def shopping(num):  #7
    print(num)  # 8
    return 1    # 9

print(shopping(5))  # 4

 

 

  這樣你調 shopping 時, 真實狀況是你在調用 inner 函數。若是 你想打印其函數名時打印的實際上是 innner 函數。函數

from functools import wraps
def wrapper(func):  # 2
    @wraps(func)
    def inner(*args,**kwargs):  # 5
        ret = func(*args,**kwargs)  # 6
        return ret  #10
    return inner   # 3

@wrapper  #shopping = wrappers(shooping)   # 1 --shopping = innner
def shopping(num):  #7
    print(num)  # 8
    return 1    # 9

print(shopping(5))  # 4
print(shopping.__name__)  #以字符串的形式獲取到函數名
print(shopping.__doc__)  #以字符串的形式獲取到函數註釋

  若是用內置的模塊,wraps ,就能夠輕鬆解決這個問題,使得全部的還和之前同樣,其中wraps(),中要傳入參數,參數應該與外層裝飾器的形參一致。oop

 

 

  對於裝飾器,若是你想取消個這裝飾器的功能,如今給出的方法就只能是在裝飾的外面在套一個裝飾器,並設置一個定位符(一個全局變量)來控制其是否執行:spa

control = True
def outer(flag):
        def wrapper(func):
            def inner(*args,**kwargs):
                if flag:
                    print('函數執行前')
                    ret = func(*args,**kwargs)
                    print('函數執行後')
                    return ret
                else:
                    ret = func(*args, **kwargs)
            return inner
        return wrapper

@outer(control)# shoping = outer(shopping) = wapper(shoping) = inner(shopping) 只是要多一個參數進行判斷
def shopping(num):
    print(num)
    return 1

shopping(5)

  

 

  多個裝飾器進行嵌套,裝飾器的糖的運行是,就近原則,離函數最近的糖先運行code

def wrapper1(func):  #func--shopping
    def inner(*args,**kwargs):
        print('000函數執行前')
        ret = func(*args,**kwargs)
        print('000函數執行後')
        return ret
    return inner

def wrapper2(func):  #func--inner1
    def inner(*args,**kwargs):
        print('111函數執行前')
        ret = func(*args,**kwargs)  #這裏的調用實際上是使用 inner1() 函數
        print('111函數執行後')
        return ret
    return inner

@wrapper2
@wrapper1
def shopping(num):
    print(num)
    return 1

shopping(5)
'''
111函數執行前
000函數執行前
5
000函數執行後
111函數執行後
'''

 

 

  來個做業orm

# 在12 天做業 編寫裝飾器,爲多個函數加上認證功能(用戶的帳號來源於文件),
# 要求登入一次成功,後續的函數都無需再輸入用戶和密碼
def wrapper(func):
    def inner(*args, **kwargs):
        with open('ver', mode='r+',encoding='utf-8')as f:
           flag = f.read()
           if  flag:
                verification = input('>>>').strip()
                if verification == 'eli123':
                    # f.seek(0)
                    f.truncate(0,)
                    ret = func(*args, **kwargs)
                    return ret
           else:
               ret = func(*args, **kwargs)
               return ret
    return inner

@wrapper
def buy(num):
    print('買了{}個包子'.format(num))
@wrapper
def eat(num):
    print('吃了{}個包子'.format(num))
with open('ver',mode='w',encoding='utf-8') as f:
    f.write('aaa')
buy(3)
eat(2)

  這裏利用了一個文件,在進行函數前,生成內容,而後文件中有內容時,要求驗證 驗證碼,而後刪除,方便第二次的驗證。blog

 

 

# 2.編寫裝飾器,爲多個函數加上記錄調用功能,要求每次調用函數都將被調用的函數名稱寫入文件
from functools import wraps
def wrapper(func):
    wraps(func)
    def inner(*args, **kwargs):
        with open('record',mode='a',encoding='utf-8') as f:
            f.write(func.__name__ + '\n')
        ret = func(*args, **kwargs)
        return ret
    return inner

@wrapper
def buy(num):
    print('買了{}個包子'.format(num))
@wrapper
def eat(num):
    print('吃了{}個包子'.format(num))

buy(3)
eat(2)

  與第一題相比,確實比較容易一點(以後學到時間模塊,能夠加入時間模塊的)ip

相關文章
相關標籤/搜索