一、裝飾器也相當閉包函數,就是給函數增加額外功能的函數,它本質就是一個閉包函數。
裝飾器的功能特點:
1、不修改已有函數的源代碼
2、不修改已有函數的調用方式
3、給已有函數增加額外的功能
目的:對已有函數進行額外的功能擴展
def decorator(func):
def inner():
print("已添加登錄驗證")
func()
return inner
def comment():
print("發表評論")
comment = decorator(comment)
comment()
前提條件是嵌套函數 ,個人認為跟java中Spring框架Aop特性有些類似,在不改變原有方法的基礎上,增加額外的內容,類似環繞。
裝飾器語法糖寫法, 裝飾器函數的名字。
def decorator(func):
def inner():
print("已添加登錄驗證")
func()
return inner
# 裝飾器語法糖寫法, 裝飾器函數的名字
@decorator # decorator相當於 comment = decorator(comment)
def comment():
print("發表評論")
# comment = decorator(comment)
comment()
裝飾器的執行時機:當前模塊加載完畢後,裝飾器會立即執行,對已有函數進行裝飾。
二、裝飾器的使用場景
1、函數執行時間的統計
2、輸出日志信息
import time
def decorator(func):
def inner():
begin = time.time()
func()
end = time.time()
result = end - begin
print(result)
return inner
@decorator
def work():
for i in range(10000):
print(i)
work()
三、通用裝飾器的使用
1、裝飾帶有參數的函數
使用裝飾器裝飾已有函數的時候,內部函數的類型,要和裝飾的已有函數的類型保持一致
特點是有參數,沒有返回值
# 通用的裝飾器,可以裝飾任意類型的函數
# 裝飾帶有參數的函數
def decorator(func):
def inner(a, b):
# 在內部函數對已有函數進行裝飾
print("正在努力執行加法計算")
func(a, b)
return inner
# 使用語法糖方式含義等價於 ,add_num = decorator(add_num) add_num = inner
@decorator
def add_num(num1, num2):
result = num1 + num2
print("結果為:", result)
add_num(2, 4)
有參數有返回值的,
# 裝飾帶有參數的函數,有返回值
def decorator(func):
def inner(a, b):
# 在內部函數對已有函數進行裝飾
print("正在努力執行加法計算")
num = func(a, b)
return num
return inner
# add_num = decorator(add_num), add_num = inner
@decorator
def add_num(num1, num2):
result = num1 + num2
return result
result1 = add_num(2, 4)
print("結果為:", result1)
裝飾帶有不定長參數和返回值的函數,這個裝飾器可以被稱為通用的裝飾器
# 裝飾帶有不定長的參數和返回值的函數
def decorator(func):
def inner(*args, **kwargs):
print("正在努力執行加法計算")
num = func(*args, **kwargs)
return num
return inner
@decorator
def add_num(*args, **kwargs):
result = 0
# *args 元組類型,把元組裡面的每一個元素,按照位置參數的方式進行傳參
# **kwargs 字典類型,把字典裡的每一個鍵值對,按照關鍵字的方式進行傳參
# 這裡對元組和字段進行閉包,僅限於結合不定長參數的函數使用
for value in args:
result += value
for value in kwargs.values():
result += value
return result
result1 = add_num(1, 2)
print("結果為:", result1)
四、多個裝飾器的使用,多個裝飾器的過程,由內到外的一個裝飾過程 ,先執行內部的裝飾器,再執行外部的裝飾器。
def make_p(func):
print("make_p裝飾器執行了")
def inner():
result = "<p>" + func() + "</p>"
return result
return inner
def make_div(func):
print("make_div裝飾器執行了")
def inner():
result = "<div>" + func() + "</div>"
return result
return inner
@make_div
@make_p
def content():
return "多個裝飾器的使用"
test = content()
print(test)
執行結果
make_p裝飾器執行了
make_div裝飾器執行了
<div><p>多個裝飾器的使用</p></div>
五、帶有參數的裝飾器
帶有參數的裝飾器就是使用裝飾器裝飾函數的時候可以傳入指定參數,語法格式:@裝飾器(參數)
def return_decorator(flag):
# 裝飾器,裝飾器只能接收一個參數並且是函數類型
def decorator(func):
def inner(a, b):
if flag == "+":
print("正在努力執行加法計算")
elif flag == "-":
print("正在努力執行減法計算")
func(a, b)
return inner
return decorator
@return_decorator("+")
def add_number(a, b):
result = a + b
print(result)
@return_decorator("-")
def sub_number(a, b):
result = a - b
print(result)
add_number(1, 4)
sub_number(1, 7)
# 正在努力執行加法計算
# 5
# 正在努力執行減法計算
# -6
六、類裝飾器
使用類裝飾器裝飾已有函數
需要在類裡面增加初始化方法,並且實現call方法,讓對象變為可調用的對象。可調用對象能夠像函數使用。
# 類裝飾器,使用類裝飾已有函數
class MyDecorator(object):
def __init__(self, func):
self._func =func
def __call__(self, *args, **kwargs):
print("課程已講完")
self._func()
@MyDecorator
def show():
print("快要下課了")
show()
# 課程已講完
# 快要下課了