"""
开放封闭原则:
开放:对代码的拓展是开放的
封闭:对源码的修改是封闭的
装饰器:
装饰器本身就是一个函数,装饰器的本质是闭包。装饰器遵循开放封闭原则。
装饰器装饰一个函数时,在不改变原函数的源码以及调用方式的前提下,给原函数增加额外的新功能
"""
import time
# 1、原始版装饰器
def login_csdn():
time.sleep(2)
print('欢迎登录CSDN社区')
def time_test(func): # func = login_csdn函数的地址
"""测试登录csdn社区函数的执行效率"""
def inner():
start_time = time.time()
func() # login_csdn() 这里是闭包,内层函数对外层函数非全局变量的引用
end_time = time.time()
print(f'该函数执行效率为:{end_time - start_time}')
return inner
login_csdn = time_test(login_csdn) # 左边login_csdn变量得到的是 inner函数的内存地址
login_csdn() # inner()
# 2、标准版装饰器: 装饰器函数要写在所有被装饰函数的最上面 (此版本被装饰函数无返回值,但是有返回值被装饰函数却不能得到返回值,不完美)
def time_test(func): # func = login_csdn函数的地址
"""测试登录csdn社区函数的执行效率"""
def inner():
start_time = time.time()
func() # login_csdn() 这里是闭包,内层函数对外层函数非全局变量的引用
end_time = time.time()
print(f'该函数执行效率为:{end_time - start_time}')
return inner
# @time_test叫语法糖,相当于这句 login_csdn = time_test(login_csdn)。
# 代码执行到“@time_test”这行时,会同时执行下面“def login_csdn():”这行,
# 拿到函数名的地址,然后执行login_csdn = time_test(login_csdn)这句代码,把函数名地址传给装饰器函数time_test
@time_test
def login_csdn():
time.sleep(2)
print('欢迎登录CSDN社区')
login_csdn()
# 3、标准版装饰器: 装饰器函数要写在所有被装饰函数的最上面 (被装饰函数具有返回值)
def time_test(func): # func = login_csdn函数的地址
"""测试登录csdn社区函数的执行效率"""
def inner():
start_time = time.time()
res_return = func() # login_csdn() 这里是闭包,内层函数对外层函数非全局变量的引用
end_time = time.time()
print(f'该函数执行效率为:{end_time - start_time}')
return res_return
return inner
# @time_test叫语法糖,相当于这句 login_csdn = time_test(login_csdn)。
# 代码执行到“@time_test”这行时,会同时执行下面“def login_csdn():”这行,
# 拿到函数名的地址,然后执行login_csdn = time_test(login_csdn)这句代码,把函数名地址传给装饰器函数time_test
@time_test
def login_csdn():
time.sleep(2)
print('欢迎登录CSDN社区')
return '777 我要返回一些数据'
# ret 实际接收的是内层函数inner的返回值,但是被装饰函数的返回值是给了装饰器里面func()函数这个执行者
# 所以内层函数的返回值只需要返回func()函数的执行者,即res_return
ret = login_csdn()
print(ret)
# 4、最标准版装饰器: 装饰器函数要写在所有被装饰函数的最上面 (被装饰函数具有返回值,被装饰函数含有参数)
def time_test(func): # func = login_csdn函数的地址
"""测试登录csdn社区函数的执行效率"""
def inner(*args, **kwargs): # 函数定义,*代表聚合
start_time = time.time()
# 函数调用,*代表打散, func(*('苏秦', 17)) == func('苏秦', 17) == login_csdn('苏秦', 17)
res_return = func(*args, **kwargs) # login_csdn() 这里是闭包,内层函数对外层函数非全局变量的引用。
end_time = time.time()
print(f'该函数执行效率为:{end_time - start_time}')
return res_return
return inner
# @time_test叫语法糖,相当于这句 login_csdn = time_test(login_csdn)。
# 代码执行到“@time_test”这行时,会同时执行下面“def login_csdn():”这行,
# 拿到函数名的地址,然后执行login_csdn = time_test(login_csdn)这句代码,把函数名地址传给装饰器函数time_test
@time_test
def login_csdn(name, age):
time.sleep(2)
print(f'欢迎{name}登录CSDN社区, 今年{age}岁!!!')
return '777 我要返回一些数据'
# ret 实际接收的是内层函数inner的返回值,但是被装饰函数的返回值是给了装饰器里面func()函数这个执行者
# 所以内层函数的返回值只需要返回func()函数的执行者,即res_return
ret = login_csdn('苏秦', 17)
print(ret)
# 5、最终标准版装饰器模板
def wrapper(func):
def inner(*args, **kwargs):
"""
这里添加:
执行被装饰函数之前的操作
"""
ret = func(*args, **kwargs)
"""
这里添加:
执行被装饰函数之后的操作
"""
return ret
return inner
Python 装饰器
于 2022-02-17 23:21:48 首次发布