Python之装饰器-带参装饰器
带参装饰器
- @之后不是一个单独的标识符,是一个函数调用
- 函数调用的返回值又是一个函数,此函数是一个无参装饰器
- 带参装饰器,可以有任意个参数
- @func()
- @func(1)
- @func(1, 2)
python
复制代码
def add(x, y):
"""
函数说明:
参数说明
返回值说明
"""
pass
# 先写一段伪代码
python
复制代码
add.__name__, add.__doc__
# add的名字是什么,add的文档是什么
# 返回结果:('add', '\n 函数说明:\n \n 参数说明\n 返回值说明\n ')
python
复制代码
help(add) # 查看帮助
# add的名字是什么,add的文档是什么
# 返回结果:Help on function add in module __main__:
# 返回结果:add(x, y)
# 返回结果: 函数说明:
# 返回结果: 参数说明
# 返回结果: 返回值说明
python
复制代码
import datetime # 导入datetime模块
start = datetime.datetime.now() # 开始时间
end = datetime.datetime.now() # 结束时间
python
复制代码
def logger(wrapped):
def wrapper(*args, **kwargs):
"wrapper +++"
start = datetime.datetime.now()
ret = wrapped(*args, **kwargs)
delta = (datetime.datetime.now() - start).total_seconds()
print("{} tooks {}s.".format(wrapped.__name__, delta))
return ret
wrapper.__name__ = wrapped.__name__ # 通过这行,使装饰器装的更像
wrapper.__doc__ = wrapped.__doc__
return wrapper
@logger # 等价式, add = logger(add) # logger应该等效为单参函数
def add(x, y): # add = wrapper
"add description~~"
#time.sleep(2)
return x + y
print(add(4, 5)) # 非侵入代码,完成了功能,并且好像从来没有装饰过一样
print(add.__name__, add.__doc__)
# 此为无参装饰器,已次代码为例演示带参装饰器。
# 返回结果:add tooks 4e-06s.
# 返回结果:9
# 返回结果:add add description~~
python
复制代码
# def update(wrapper, wrapped):
# wrapper.__name__ = wrapped.__name__ # 通过这行,使装饰器装的更像
# wrapper.__doc__ = wrapped.__doc__
# 可以通过函数来调用,因为重复使用,不需要每次都创建,写到函数外方便调用
# def update(src, dest): # 见名知意,这样写,src=源,dest=目标
# dest.__name__ = src.__name__
# dest.__doc__ = src.__doc__
# from functools import update_wrapper # python内置函数调用
from functools import update_wrapper, wraps # 装饰器版本
def logger(wrapped):
@wraps(wrapped) # 装饰器版本
def wrapper(*args, **kwargs):
"wrapper +++"
start = datetime.datetime.now()
ret = wrapped(*args, **kwargs)
delta = (datetime.datetime.now() - start).total_seconds()
print("{} tooks {}s.".format(wrapped.__name__, delta))
return ret
#wrapper.__name__ = wrapped.__name__ # 通过这行,使装饰器装的更像
#wrapper.__doc__ = wrapped.__doc__
#update(wrapper, wrapped)
#update(wrapped, wrapper)
#update_wrapper(wrapper, wrapped) # 调用
return wrapper
@logger # 等价式, add = logger(add) # logger应该等效为单参函数
def add(x, y): # add = wrapper
"add description~~"
#time.sleep(2)
return x + y
print(add(4, 5)) # 非侵入代码,完成了功能,并且好像从来没有装饰过一样
print(add.__name__, add.__doc__)
# 带参装饰器的对比解释版本
# 返回结果:add tooks 6e-06s.
# 返回结果:9
# 返回结果:add add description~~
python
复制代码
from functools import update_wrapper, wraps
def logger(wrapped):
@wraps(wrapped) # 等价式 wrapper = wraps(wrapped)(wrapper) # partial function(偏函数)
def wrapper(*args, **kwargs):
"wrapper +++"
start = datetime.datetime.now()
ret = wrapped(*args, **kwargs)
delta = (datetime.datetime.now() - start).total_seconds()
print("{} tooks {}s.".format(wrapped.__name__, delta))
return ret
return wrapper
@logger # 等价式, add = logger(add) # logger应该等效为单参函数
def add(x, y): # add = wrapper
return x + y
@logger
def sub(x, y):
return x - y
#print(add(5, 4))
#print(sub(5, 4))
print(add.__name__, sub.__name__)
# 函数,函数执行过程,函数作用域,形参,实参,解构,嵌套函数,LEGB、高阶,柯里化,闭包
# 返回结果:add sub