python_之无参装饰器_01

# 1:提问:什么是装饰器?
#   解答:根据字面意思可以理解,装饰器就是用来装饰函数的工具。
#
# 2:装饰器有什么特点?
#   解答:(1) 装饰器原则:开放封闭原则。 解释==》开放是指,对外开放,封闭是指:不修改原代码。
#      (2) 特点1:给被装饰函数添加新功能
#      (3) 特点2: 调用被装饰函数
#
# 3:小案例: 给index()函数加上计时器

# import time
# def index(name):
# print(f"欢迎{name}来到这里")
# return "我是index的返回值"
#
# def home(name):
# print(f"欢迎{name}回家了")

# (1) 不改变源代码,不改变调用方式
# start_time = time.time()
# index("madison")
# sto_time = time.time()

# 问题1==》如果项目中有很多地方调用的话,会出现代码冗余的问题。==》优化方案如下:封装它
# 这样一来,我们就解决了代码冗余问题:

# def wrapper():
# start_time = time.time()
# index("madison")
# stop_time = time.time()

# 问题2:虽说解决了代码冗余问题,但是我们这里index()的参数写死了,
# 并且这个装饰器里面的调用的函数写死了

# 只能调用index(),如果还有一个功能home()怎么办?
# 优化方案如下 ==》
# (1):解决传参问题 ==》 利用(*args, **keargs) 进行传参和解包
# (2):解决index()函数写死问题,利用闭包传参
# import time
# def outter(func):
# def wrapper(*args, **kwargs):
# start_time = time.time()
# func(*args, **kwargs) # 对传进来的参数进行解包!
# stop_time = time.time()
# return wrapper # 返回wrapper的内存地址
#
# wrapper = outter(index)
# wrapper("madison")
# print("====================")
# wrapper = outter(home) # 在试试调用home上面忘记试了,看好不好使
# wrapper("madison")
# 这里我解释下:return wrapper是因为,wrapper之前是全局变量,现在被我们写成局部变量了,
# 所以在这里

# 我们需要把它变回去,所以我们就返回它的内存地址,
# 上面我们调用outter(index)就是得到的wrapper的内存

# 地址,这里赋值给wrapper所以此时 wrapper又变回成了全局变量然后传参调用wrapper即可!

# 问题3:上面我们已经解决了写死函数和传参问题,那么还有个问题就是返回值的问题?
# 假如index有返回值,怎么办?

# import time
# def outter(func):
# def wrapper(*args, **kwargs):
# start_time = time.time()
# res = func(*args, **kwargs) # 对传进来的参数进行解包!
# stop_time = time.time()
# return res
# return wrapper # 返回wrapper的内存地址
#
# wrapper = outter(index)
# print(wrapper("madison"))
# 优化方式:看上面,我们知道index的返回值这个装饰器内部,它是func=index,所以index返回啥,我们func就返回
# 啥就可以了,所以就有了上面的 return res,对了你可以试试在wrapper内部不接收打印,结果会是None,原因是因为
# 我们现在调用的其实是wrapper,而不是index,有的小伙伴可能会蒙蔽,我上面明明就是调用的wrapper....这个问题
# 你要回去了解下闭包原理了(这里第二种传参是闭包原理,不理解最好看一边后在看上面的列子)。其实这里我们可以把
# wrapper = outter(index)改成 index = outter(index),你看,这样我们是不是就 没有修改源码和调用方式


# 问题4:上面我们已经做到,不修改源码和调用方式,就做了一个装饰功能,但是还有问题,我们每次调用的时候都要去定义
# wrapper = outter(index)/# wrapper = outter(home),我们需要优化下,方法是:@(语法糖的意思,甜甜
# 的嘿嘿。)
import time
def outter(func):
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs) # 对传进来的参数进行解包!
stop_time = time.time()
return res
return wrapper # 返回wrapper的内存地址

# index = outter(index)
# print(index("madison"))

# 问题4的优化方案:在我们需要调用装饰器的头上写上 @outter 即可
@outter
def index(name):
print(f"欢迎{name}来到这里")
return "我是index的返回值"

@outter # 它在这做了下面几件事
# 1:调用outter ==> outter()
# 2: 将被装饰(index)传进去 ==》 outter(index)
# 3: 赋值给变量,变量名被装饰自己 ==》 index = outter(index)
def home(name):
print(f"欢迎{name}回家了")

最后附上本节的完整代码的图片


   我这里总结下无参装饰器的模板:


下一节我们继续补充无参装饰器的知识,和有参装饰器的知识:


 

原文地址:https://www.cnblogs.com/haibaiwuchang/p/13258454.html