持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情
0 环境
- 编辑器:pycharm或者vscode
- 系统版本:windows10
- python版本:3.9.6
1 wrapped
上下文关键到底是应用在哪块儿的呢。比如现在临时有个小需求,我要给导入、导出加个成功提示,提示内容需要包括导入、导出了多少条,比如说导入,是为了核对是否全部导入了,本来这件事就结束了,后来呢,在这个条数显示的基础上,再追加个耗时的提示。假如很多处要用到它,是不是会想到用装饰器搞定了。例如函数()()这种形式。好比计时,可不可以用上下文管理呢,如下代码:
from datetime import datetime
class Keeptime:
def __enter__(self):
self.start = datetime.now()
def __exit__(self, *args, **kwargs):
result = datetime.now() - self.start
print("时间 -->", result)
with Keeptime():
for i in range(100):
pass
假如我又想拥有装饰器的那种功能,也不想丢失上下文管理计时的功能,如下代码: 了解即可。要想这里self.__wrapped__生效,就必须调用wraps(f)(self)。
from datetime import datetime
from functools import wraps
class Keeptime:
def __init__(self, f=None):
print("f -->", f)
wraps(f)(self)
print("__wrapped__ -->", self.__wrapped__)
def __call__(self, *args, **kwargs):
start = datetime.now()
test = self.__wrapped__(*args, **kwargs)
result = datetime.now() - start
print("call计时 -->", result)
return test
def __enter__(self):
self.start = datetime.now()
def __exit__(self, *args, **kwargs):
result = datetime.now() - self.start
print("时间 -->", result)
with Keeptime():
for i in range(100):
pass
@Keeptime
def delNum(a, b):
return a - b
delNum(4, 1)
继续self.wrapped,当我没使用wraps前是没有__wrapped__,调用后才有的它。不太好理解,可以先写个简单的函数,然后打印出wraps使用前后的变化(wraps(函数)(类实例)),调用dir(xxx)查看结果就知道了。
2 总结
通过__init__和__call__也可以实现类似装饰器的计时功能,而且对上下文管理(它通常是写成一个类)的计时功能也不影响,相互不影响也就可以说明,我们既可以对函数装饰,也不放过对代码块的装饰,鱼和熊掌兼得之。应用场景:权限校验,插入日志之类的等。