目錄
一、裝飾器
1. 裝飾器的定義
2. 裝飾器的示例代碼
3. 裝飾器的語法糖寫法
二、裝飾器的使用
1. 裝飾器的使用場景
2. 裝飾器實現已有函數執行時間的統計
三、通用裝飾器的使用
1. 裝飾帶有參數的函數
2. 裝飾帶有返回值的函數
3. 裝飾帶有不定長參數的函數
4. 通用裝飾器
四、多個裝飾器的使用
1. 多個裝飾器的使用示例代碼
五、帶有參數的裝飾器
1. 帶有參數的裝飾器介紹
六、類裝飾器
1. 類裝飾器的介紹
就是給已有函數增加額外功能的函數,它本質上就是一個閉包函數。
裝飾器的功能特點:
# 添加一個登錄驗證的功能
def check(fn):
def inner():
print("請先登錄....")
fn()
return inner
def comment():
print("發表評論")
# 使用裝飾器來裝飾函數
comment = check(comment)
comment()
# 裝飾器的基本雛形
# def decorator(fn): # fn:目標函數.
# def inner():
# '''執行函數之前'''
# fn() # 執行被裝飾的函數
# '''執行函數之後'''
# return inner
代碼說明:
執行結果:
請先登錄....
發表評論
如果有多個函數都需要添加登錄驗證的功能,每次都需要編寫func = check(func)這樣代碼對已有函數進行裝飾,這種做法還是比較麻煩。
Python給提供了一個裝飾函數更加簡單的寫法,那就是語法糖,語法糖的書寫格式是: @裝飾器名字,通過語法糖的方式也可以完成對已有函數的裝飾
# 添加一個登錄驗證的功能
def check(fn):
print("裝飾器函數執行了")
def inner():
print("請先登錄....")
fn()
return inner
# 使用語法糖方式來裝飾函數
@check
def comment():
print("發表評論")
comment()
說明:
執行結果:
請先登錄....
發表評論
import time
# 裝飾器函數
def get_time(func):
def inner():
begin = time.time()
func()
end = time.time()
print("函數執行花費%f" % (end-begin))
return inner
@get_time
def func1():
for i in range(100000):
print(i)
func1()
執行結果:
...
99995
99996
99997
99998
99999
函數執行花費0.329066
# 添加輸出日志的功能
def logging(fn):
def inner(num1, num2):
print("--正在努力計算--")
fn(num1, num2)
return inner
# 使用裝飾器裝飾函數
@logging
def sum_num(a, b):
result = a + b
print(result)
sum_num(1, 2)
運行結果:
--正在努力計算--
3
# 添加輸出日志的功能
def logging(fn):
def inner(num1, num2):
print("--正在努力計算--")
result = fn(num1, num2)
return result
return inner
# 使用裝飾器裝飾函數
@logging
def sum_num(a, b):
result = a + b
return result
result = sum_num(1, 2)
print(result)
運行結果:
--正在努力計算--
3
# 添加輸出日志的功能
def logging(fn):
def inner(*args, **kwargs):
print("--正在努力計算--")
fn(*args, **kwargs)
return inner
# 使用語法糖裝飾函數
@logging
def sum_num(*args, **kwargs):
result = 0
for value in args:
result += value
for value in kwargs.values():
result += value
print(result)
sum_num(1, 2, a=10)
運行結果:
--正在努力計算--
13
# 添加輸出日志的功能
def logging(fn):
def inner(*args, **kwargs):
print("--正在努力計算--")
result = fn(*args, **kwargs)
return result
return inner
# 使用語法糖裝飾函數
@logging
def sum_num(*args, **kwargs):
result = 0
for value in args:
result += value
for value in kwargs.values():
result += value
return result
@logging
def subtraction(a, b):
result = a - b
print(result)
result = sum_num(1, 2, a=10)
print(result)
subtraction(4, 2)
運行結果:
--正在努力計算--
13
--正在努力計算--
2
# 通用裝飾器
def logging(fn):
def inner(*args, **kwargs):
print("--正在努力計算--")
result = fn(*args, **kwargs)
return result
return inner
def make_div(func):
"""對被裝飾的函數的返回值 div標簽"""
def inner():
return "<div>" + func() + "</div>"
return inner
def make_p(func):
"""對被裝飾的函數的返回值 p標簽"""
def inner():
return "<p>" + func() + "</p>"
return inner
# 裝飾過程: 1 content = make_p(content) 2 content = make_div(content)
# content = make_div(make_p(content))
@make_div
@make_p
def content():
return "人生苦短"
result = content()
print(result)
代碼說明:
帶有參數的裝飾器就是使用裝飾器裝飾函數的時候可以傳入指定參數,語法格式: @裝飾器(參數,...)
錯誤寫法:
def decorator(fn, flag):
def inner(num1, num2):
if flag == "+":
print("--正在努力加法計算--")
elif flag == "-":
print("--正在努力減法計算--")
result = fn(num1, num2)
return result
return inner
@decorator('+')
def add(a, b):
result = a + b
return result
result = add(1, 3)
print(result)
執行結果:
Traceback (most recent call last):
File "/home/python/Desktop/test/hho.py", line 12, in <module>
@decorator('+')
TypeError: decorator() missing 1 required positional argument: 'flag'
代碼說明:
正確寫法:
在裝飾器外面再包裹上一個函數,讓最外面的函數接收參數,返回的是裝飾器,因為@符號後面必須是裝飾器實例。
# 添加輸出日志的功能
def logging(flag):
def decorator(fn):
def inner(num1, num2):
if flag == "+":
print("--正在努力加法計算--")
elif flag == "-":
print("--正在努力減法計算--")
result = fn(num1, num2)
return result
return inner
# 返回裝飾器
return decorator
# 使用裝飾器裝飾函數
@logging("+")
def add(a, b):
result = a + b
return result
@logging("-")
def sub(a, b):
result = a - b
return result
result = add(1, 2)
print(result)
result = sub(1, 2)
print(result)
裝飾器還有一種特殊的用法就是類裝飾器,就是通過定義一個類來裝飾函數。
類裝飾器示例代碼:
class Check(object):
def __init__(self, fn):
# 初始化操作在此完成
self.__fn = fn
# 實現__call__方法,表示對象是一個可調用對象,可以像調用函數一樣進行調用。
def __call__(self, *args, **kwargs):
# 添加裝飾功能
print("請先登陸...")
self.__fn()
@Check
def comment():
print("發表評論")
comment()
代碼說明:
執行結果:
請先登陸...
發表評論