1. 程式人生 > 其它 >python函式裝飾器

python函式裝飾器

目錄

裝飾器

一. 什麼是裝飾器

器:指的是工具

裝飾:給被裝飾物件新增額外的功能

二. 裝飾器的原則

開放:對擴充套件開放

封閉:對修改封閉

三. 裝飾器核心思想

在不改變被"裝飾物件內部程式碼"和"原有呼叫方式"的基礎之上新增額外功能

四. 裝飾器簡易版本

# 給函式新增統計執行時間的功能

def outer(func):  # func指向的是函式名index
    # func = index
    def get_time():
        start_time = time.time()
        func()
        end_time = time.time()
        print('函式執行時間:%s' % (end_time - start_time))
    return get_time  # 將get_time函式名返回出去
index = outer(index)  # outer(index函式名)
# 左側的變數名index指代是函式名get_time
index()

五. 解決引數問題

import time
def login(name):
    time.sleep(1)
    print('%s正在發牌'%name)
def outer(func):  # func指向的是函式名login
    # func = login
    def get_time(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)
        end_time = time.time()
        print('函式執行時間:%s' % (end_time - start_time))
    return get_time  # 將get_time函式名返回出去
login = outer(login)
login('jason')

六. 解決返回值問題

import time

def login(name):
    time.sleep(1)
    print('%s正在發牌'%name)
    return 'from login'
def outer(func):  # func指向的是函式名login
    # func = login
    def get_time(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)  # 接收被裝飾函式的返回值
        end_time = time.time()
        print('函式執行時間:%s' % (end_time - start_time))
        return res  # 執行完get_time之後返回被裝飾函式執行之後的返回值
    return get_time  # 將get_time函式名返回出去

login = outer(login)
res1 = login('jason')
print(res1)

七. 一次性登入認證( 練習)

import time

def index():
    time.sleep(1)
    print('百萬大獎等你來拿  趕快來加入我們把!!!')

def home():
    time.sleep(1)
    print('學學學  一天到晚就是學  卷死你們這些傢伙')

def register():
    time.sleep(1)
    print('註冊功能.')

dic = {'state': False}
def outter(func):
    def inter(*args, **kwargs):
        while True:
            if dic['state'] == False:  # 驗證之前是否已經成功登陸
                username = input('請輸入使用者名稱>>>:').strip()  # 增加功能
                pwd = input('請輸入密碼>>>:').strip()
                if username == 'jason' and pwd == '123':
                    dic['state'] = True  # 登入成功則之後不需要再次驗證登入
                    res = func(*args, **kwargs)
                    return res
                else:
                    print('使用者名稱或密碼錯誤.')
                    # return res
            else:
                res = func(*args, **kwargs)
                return res
    return inter
# 這樣就可以驗證一次登入就直接依次執行後續操作
index = outter(index)
index()
home = outter(home)
home()
register = outter(register)
register()

八. 裝飾器固定模板

def outer(func):
    def inner(*args, **kwargs):
        print('執行函式之前可以新增的額外功能')
        res = func(*args, **kwargs)  # 執行被裝飾的函式
        print('執行函式之後可以新增的額外功能')
        return res  # 將被裝飾函式執行之後的返回值返回
    return inner
# 呼叫的時候用
@outer
def xx():
# 這樣函式xx就擁有了函式outer的裝飾器功能了

九. 裝飾器語法糖

  • 裝飾器語法糖書寫規範

    語法糖必須緊貼在被裝飾物件的上方

  • 裝飾器語法糖內部原理

    會自動將下面緊貼著的被裝飾物件名字當做引數傳給裝飾器函式呼叫

十. 雙層語法糖

十一. 裝飾器修復技術

from functools import wraps
def outer(func):
    @wraps(func)  # 修復技術就是為了讓被裝飾物件更加不容易被察覺裝飾了
    def inner(*args, **kwargs):
        print('執行函式之前可以新增的額外功能')
        res = func(*args, **kwargs)  # 執行被裝飾的函式
        print('執行函式之後可以新增的額外功能')
        return res  # 將被裝飾函式執行之後的返回值返回
    return inner

@outer  # index = outer(index)
def index():
    print('from index')
print(index)
help(index)
# 調from functools import wraps模組 加 @wraps(func)是讓列印改名後的index記憶體地址也是顯示函式名index 而不呼叫的話顯示實際呼叫的函式名inner

十二. 3層語法糖