-
最简装饰器
def deco(func):
def wrap(*args, **kwargs):
return func(*args, **kwargs)
return wrap@deco def foo(a, b): return a ** b
-
原理
-
对比被装饰前后的 foo.name 和 foo.doc
from functools import wrapsdef deco(func): '''i am deco''' @wraps(func) # 还原被装饰器修改的原函数属性 def wrap(*args, **kwargs): '''i am wrap''' return func(*args, **kwargs) return wrap
-
简单过程
fn = deco(func)
foo = fn
foo(*args, **kwargs) -
多个装饰器叠加调用的过程
@deco1
@deco2
@deco3
def foo(x, y):
return x ** y# 过程拆解 1 fn3 = deco3(foo) fn2 = deco2(fn3) fn1 = deco1(fn2) foo = fn1 foo(3, 4) # 过程拆解 2 # 单行: deco1( deco2( deco3(foo) ) )(3, 2) deco1( deco2( deco3(foo) ) )(3, 4)
-
-
带参数的装饰器
def deco(n):
def wrap1(func):
def wrap2(*args, **kwargs):
return func(*args, **kwargs)
return wrap2
return wrap1# 调用过程 wrap1 = deco(n) wrap2 = wrap1(foo) foo = wrap2 foo() # 单行形式 check_result(30)(foo)(4, 8)
-
装饰器类和 call
class Deco:
def init(self, func):
self.func = funcdef __call__(self, *args, **kwargs): return self.func(*args, **kwargs) @Deco def foo(x, y): return x ** y # 过程拆解 fn = Deco(foo) foo = fn foo(12, 34)
-
使用场景
- 参数、结果检查
- 缓存、计数
- 日志、统计
- 权限管理
- 重试
- 其他
-
练习1: 写一个 timer 装饰器, 计算出被装饰函数调用一次花多长时间, 并把时间打印出来
import time
from functools import wrapsdef timer(func): @wraps(func) # 修正 docstring def wrap(*args, **kwargs): time0 = time.time() result = func(*args, **kwargs) time1 = time.time() print(time1 - time0) return result return wrap
-
练习2: 写一个 Retry 装饰器
import timeclass retry(object): def __init__(self, max_retries=3, wait=0, exceptions=(Exception,)): self.max_retries = max_retries self.exceptions = exceptions self.wait = wait def __call__(self, func): def wrapper(*args, **kwargs): for i in range(self.max_retries + 1): try: result = func(*args, **kwargs) except self.exceptions: time.sleep(self.wait) continue else: return result return wrapper
python进阶之装饰器
最新推荐文章于 2021-10-26 11:06:27 发布