Python裝飾器詳情

1、裝飾器

裝飾器(Decorator):從字面上理解,就是裝飾對象的器件。可以在不修改原有代碼的情況下,為被裝飾的對象增加新的功能或者附加限制條件或者幫助輸出。

裝飾器的特點是特點是函數是作為其參數出現的,裝飾器還擁有閉包的特點。

示例代碼如下所示:

# 定義一個裝飾器
def decorate(func):
    def wrapper():
        func()
        print("已將學生加入學校學生名單")
        print("已將學生加入系學生名單")
        print("已將學生加入班級名單")

    return wrapper


@decorate
def student():
    print("我是小花")


student()
'''
---輸出結果---
我是小花
已將學生加入學校學生名單
已將學生加入系學生名單
已將學生加入班級名單
'''

使用**@****符號加函數名**來裝飾一個函數

執行流程:因為student是被裝飾的函數,系統將student函數以參數的形式傳入decorate函數(裝飾器decorate),執行decorate函數,並將返回值賦給student函數。

上一段代碼等於下面這一段代碼:

# 定義一個裝飾器
def decorate(func):
    def wrapper():
        func()
        print("已將學生加入學校學生名單")
        print("已將學生加入系學生名單")
        print("已將學生加入班級名單")

    return wrapper


def student():
    print("我是小花")


# 將返回值傳給f 並調用
f = decorate(student)  # 這裡不能加(),不然就表示調用
f()
'''
---輸出結果---
我是小花
已將學生加入學校學生名單
已將學生加入系學生名單
已將學生加入班級名單
'''

如果student函數外有直接可執行的語句,在不調用student函數的情況下,也會被執行,

示例代碼如下:

# 定義一個裝飾器
def decorate(func):
    print("這是外部的代碼")

    def wrapper():
        func()
        print("已將學生加入學校學生名單")
        print("已將學生加入系學生名單")
        print("已將學生加入班級名單")

    return wrapper


@decorate
def student():
    print("我是小花")


# student()
'''
---輸出結果---
這是外部的代碼
'''

1.1 應用場景

可以用於電商網站的判斷用戶是否登錄來是否繼續往下執行;添加日志等場景,

示例代碼如下所示:

# 定義一個裝飾器
def decorate(func):
    def wrapper():
        func()
        print("正在檢驗用戶是否登錄")
        # if  # 判斷是否登錄的代碼塊
        #     pass
        print("用戶已登錄")

    return wrapper


@decorate  # 使用裝飾器
def add_shopping_cart():
    print("添加成功")


@decorate  # 使用裝飾器
def payment():
    print("付款成功")


add_shopping_cart()
payment()

'''
---輸出結果---
添加成功
正在檢驗用戶是否登錄
用戶已登錄
付款成功
正在檢驗用戶是否登錄
用戶已登錄
'''

2、萬能裝飾器

因為函數的參數可能是不固定的,所以可以通過函數的可變參數來完成這種功能。

示例代碼如下:

def decorate(func):
    def wrapper(*args, **kwargs):  # 使用可變參數來達到可以接受任何參數的效果
        print("正在檢測中。。。")
        print(".............")
        print("檢測完畢")
        func(*args, **kwargs)

    return wrapper


@decorate  # 使用裝飾器
def f1():  # 無參數
    print("這個沒有任何功能")


@decorate
def f2(name):  # 一個參數
    print("名字是:", name)


@decorate
def student(*students):  # 多個參數  # *students用於接收多個參數
    for ch in students:
        print(ch)


@decorate
def student_classroom(*students, classroom="前端班"):  # 接收可以賦值的參數
    print(f"這是{classroom}的學生")
    for ch in students:
        print(ch)


# 調用函數
f1()
'''
---輸出結果---
正在檢測中。。。
.............
檢測完畢
這個沒有任何功能
'''
f2("一碗周")
'''
---輸出結果---
正在檢測中。。。
.............
檢測完畢
名字是: 一碗周
'''
student("張三", "李四", "王五")
'''
---輸出結果---
正在檢測中。。。
.............
檢測完畢
張三
李四
王五
'''
student_classroom("張三", "李四", "王五", classroom="前端班")
'''
正在檢測中。。。
.............
檢測完畢
這是前端班的學生
張三
李四
王五
'''

為瞭防止錯誤,在定義裝飾器的時候要將其設置為萬能裝飾器

3、多層裝飾器

多層的執行循序執行順序是從裡到外,最先調用最裡層的裝飾器,最後調用最外層的裝飾器,

示例代碼如下所示:

def maths(func):  # 定義第一個裝飾器
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        print("該學生已經學習瞭數學")

    return wrapper


def Chinese(func):  # 定義第而個裝飾器
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        print("該學生已經學習瞭語文")

    return wrapper


def English(func):  # 定義第三個裝飾器
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        print("該學生已經學習瞭英語")

    return wrapper


@maths
@English
def student1(name):
    print(f"學生{name}已經完成瞭")


@English
@Chinese
@maths
def student2(name):
    print(f"學生{name}已經完成瞭")


# 調用函數
student1("小明")
'''
學生小明已經完成瞭
該學生已經學習瞭英語
該學生已經學習瞭數學
'''
student2("小花")
'''
學生小花已經完成瞭
該學生已經學習瞭數學
該學生已經學習瞭語文
該學生已經學習瞭英語
'''

4、帶參數的裝飾器

帶參數的裝飾器一共分為三層,分別如下:

  • 第一層:負責接收裝飾器的參數
  • 第二層 :負責接收函數
  • 第三層:負責接收函數的參數

示例代碼如下所示:

# 裝飾器帶參數
def outer(a):  # 第一層: 負責接收裝飾器的參數

    def decorate(func):  # 第二層 : 負責接收函數

        def wrapper(*args, **kwargs):  # 第三層   負責接收函數的參數
            for i in range(a):
                print(i)
            func(*args, **kwargs)

        return wrapper  # 返出來的是:第三層

    return decorate  # 返出來的是:第二層


@outer(3)
def number():
    print("打印完畢")


number()
'''
0
1
2
打印完畢
'''

最外層的函數負責接收裝飾器參數,裡面的內容還是原裝飾器的內容。

到此這篇關於Python裝飾器詳情的文章就介紹到這瞭,更多相關Python裝飾器內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: