本篇文章小编给大家分享一下Python装饰器常用的创建方式及源码示例解析,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
基础通用装饰器
源码示例
def wrapper_out(func):
print('-- wrapper_out start --')
def inner(*args, **kwargs):
print("-- inner start --")
ret = func(*args, **kwargs)
print("-- inner end --")
return ret
print('-- wrapper_out end --')
return inner
@wrapper_out
def test():
print("--test--")
return 1 * 2
if __name__ == '__main__':
print(">>>>>>>>>>>>>>")
print(test())
执行结果
-- wrapper_out start --
-- wrapper_out end --
>>>>>>>>>>>>>>
-- inner start --
--test--
-- inner end --
2
带参数装饰器
源码示例
def wrapper_out(mode=None):
print('-- wrapper_out start --')
def inner_1(func):
print("-- inner_1 start --")
def inner_2(*args, **kwargs):
print("-- inner_2 start --")
print(f"mode: {mode}")
ret = func(*args, **kwargs)
print("-- inner_2 end --")
return ret
print("-- inner_2 end --")
return inner_2
print('-- wrapper_out end --')
return inner_1
@wrapper_out(mode=2)
def test():
print("--test--")
return 1 * 2
if __name__ == '__main__':
print(">>>>>>>>>>>>>>")
print(test())
源码结果
-- wrapper_out start --
-- wrapper_out end --
-- inner_1 start --
-- inner_2 end --
>>>>>>>>>>>>>>
-- inner_2 start --
mode: 2
--test--
-- inner_2 end --
2
源码解析
带参数的装饰器函数, 需要多嵌套一层, 外层装饰器的参数
预加载的时候已经是根据函数的编写顺序进行加载
执行顺序在对应的最内存函数中调用最外层的装饰器函数参数
被装饰函数是最为 inner_1 的参数进行传入, 被装饰函数的参数是作为 inner_2 的参数传入
被装饰函数的执行位置是在 inner_2 中, 使用inner_1 的参数变量和 inner_2 的参数变量共同协助下进行执行
同时还要使用装饰器函数 wrapper_out 的参数变量进行额外的操作
多装饰器执行顺序
源码示例
def wrapper_out1(func):
print('-- wrapper_out_1 start --')
def inner1(*args, **kwargs):
print("-- inner_1 start --")
ret = func(*args, **kwargs)
print("-- inner_1 end --")
return ret
print('-- wrapper_out1 end --')
return inner1
def wrapper_out2(func):
print('-- wrapper_out_2 start --')
def inner2(*args, **kwargs):
print("-- inner_2 start --")
print("-- inner_2 end --")
print('-- wrapper_out_2 end --')
return inner2
@wrapper_out2
@wrapper_out1
def test():
print("--test--")
return 1 * 2
if __name__ == '__main__':
print(">>>>>>>>>>>>>>")
print(test())
执行结果
-- wrapper_out_1 start --
-- wrapper_out1 end --
-- wrapper_out_2 start --
-- wrapper_out_2 end --
>>>>>>>>>>>>>>
-- inner_2 start --
-- inner_1 start --
--test--
-- inner_1 end --
-- inner_2 end --
2
解析
装饰器的预加载顺序是从上往下, 先将装饰器函数写入内存
装饰器的执行顺序是以最靠近函数体的装饰器开始执行(从内到外)
类装饰器
源码示例
class WrapperOut(object):
def __init__(self, func):
print('start init ~~~~~`')
print('func name is %s ' % func.__name__)
self.__func = func
print('end init ~~~~~`')
def __call__(self, *args, **kwargs):
print('start test')
self.__func()
print('end test')
@WrapperOut
def test():
print('this is test func')
if __name__ == '__main__':
print(">>>>>>>>>>>")
test()
执行结果
start init ~~~~~`
func name is test
end init ~~~~~`
>>>>>>>>>>>
start test
this is test func
end test
解析
类装饰器是利用了类初始化 init 析构方法来处理 被装饰函数的传入
以及使用 call 方法来满足被装饰函数的执行触发
TPLink TLWDR4320 无线路由器IP带宽控制功能分配带宽设置方法
SQL Server 2008及更高版本数据库恢复做法之日志尾部备份实用指南
TPLink TLWDR4320 无线路由器控制管控小孩上网行为设置
TPLink TLWDR4320 无线路由器打印服务器设置指南
TPLink TLWDR8620 52 无线路由器当作交换机使用教程
TPLink TLWDR8620 52 无线路由器映射服务器到外网操作方法