Python“三大器”之装饰器1

一、装饰器1、什么是装饰器?装饰:装饰、修饰
器:工具
装饰器:装饰的工具
(*****)“开放封闭”:装饰器必须要遵循“开放封闭”原则:
开放:对函数功能的添加是开放的
封闭:对函数功能的修改是封闭的
2、装饰器的作用?在不修改被装饰对象源代码与调用方式的前提下添加新的功能 。
装饰器必须遵循的两个原则:
不修改被装饰对象源代码
不修改被装饰对象的调用方式
ps:
被装饰对象指的是 ---> 需要添加功能的(函数)
装饰器指的是 ---> 被装饰对象添加的新功能的(函数)
3、为什么要使用装饰器?可以解决代码荣誉问题 , 提高代码的可扩展性
4、怎么使用装饰器?编写装饰器:
通过闭包函数来实现装饰器
装饰器的应用:
1、统计时间
2、登录认证
例子:
需求:需要统计一下下载电影的时间
方案一:函数调用(适合少次使用)
Python“三大器”之装饰器1文章插图
import timedef download_movie():print("开始下载电影...")# 模拟电影下载时间为3秒time.sleep(3)print("电影下载成功!")start_time = time.time()# 获取当前时间戳download_movie()end_time = time.time()# 获取当前时间戳print(f"消耗时间:{end_time - start_time}")
Python“三大器”之装饰器1文章插图
问题1:如果有多个被装饰对象 , 需要写多次统计时间的代码 , 导致代码冗余 , 于是有了方案二 。
方案二:使用装饰器(适合多次调用 , 调用时直接在闭包函数内传入所需要使用装饰器的函数名称)
Python“三大器”之装饰器1文章插图
import timedef download_movie():print("开始下载电影...")# 模拟电影下载时间为3秒time.sleep(3)print("电影下载成功!")# 模拟多个被装饰对象def func1():pass# 模拟多个被装饰对象def func2():pass# 装饰器:初级版def time_record(func):def inner():# 获取当前时间戳start_time = time.time()func()# 获取当前时间戳end_time = time.time()print(f"消耗时间:{end_time - start_time}")return innerdownload_movie = time_record(download_movie)download_movie()
Python“三大器”之装饰器1文章插图
问题2:如果被装饰对象有返回值 , 有参数而且有多个参数 , 于是有了方案三 。
方案三:方案二的代码优化 , 使用*args, **kwargs接收所有参数(形参 , 关键字参数等)import time
Python“三大器”之装饰器1文章插图
def download_movie(*args, **kwargs):print("开始下载电影...")# 模拟电影下载时间time.sleep(3)print("电影下载成功!")return "movie.mp4"# 装饰器最终版def time_record(func):def inner(*args, **kwargs):# *args **kwargs接收所有参数(形参 , 关键字参数等)# 获取当前时间戳start_time = time.time()# 将被装饰对象需要接收的人以参数 , 原封不动的传给func(被修饰对象)res = func(*args, **kwargs)#此处的fanc为被修饰对象download_movie()# 获取当前时间戳end_time = time.time()# 统计结束 , 打印统计时间print(f"消耗时间:{end_time - start_time}")return resreturn inner# 这里的download_movie是inner()的返回值download_movie = time_record(download_movie)# download_movie()--->inner(), 可传入任意参数 , 若传入参数 , download_movie()函数需要修改代码块 , 否则不打印或者不执行传入参数download_movie()