[python]装饰器及其使用

心已赠人 2022-03-15 10:08 263阅读 0赞

装饰器

  • 最简装饰器

    1. def deco(func):
    2. def wrap(*args, **kwargs):
    3. return func(*args, **kwargs)
    4. return wrap
    5. @deco
    6. def foo(a, b):
    7. return a ** b
  • 原理

    • 对比被装饰前后的 foo.__name__foo.__doc__

      1. from functools import wraps
      2. def deco(func):
      3. '''i am deco'''
      4. @wraps(func) # 还原被装饰器修改的原函数属性
      5. def wrap(*args, **kwargs):
      6. '''i am wrap'''
      7. return func(*args, **kwargs)
      8. return wrap
    • 简单过程

      1. fn = deco(func)
      2. foo = fn
      3. foo(*args, **kwargs)
    • 多个装饰器叠加调用的过程

      1. @deco1
      2. @deco2
      3. @deco3
      4. def foo(x, y):
      5. return x ** y
      6. # 过程拆解 1
      7. fn3 = deco3(foo)
      8. fn2 = deco2(fn3)
      9. fn1 = deco1(fn2)
      10. foo = fn1
      11. foo(3, 4)
      12. # 过程拆解 2
      13. # 单行: deco1( deco2( deco3(foo) ) )(3, 2)
      14. deco1(
      15. deco2(
      16. deco3(foo)
      17. )
      18. )(3, 4)
  • 带参数的装饰器

    1. def deco(n):
    2. def wrap1(func):
    3. def wrap2(*args, **kwargs):
    4. return func(*args, **kwargs)
    5. return wrap2
    6. return wrap1
    7. # 调用过程
    8. wrap1 = deco(n)
    9. wrap2 = wrap1(foo)
    10. foo = wrap2
    11. foo()
    12. # 单行形式
    13. check_result(30)(foo)(4, 8)
  • 装饰器类和 __call__

    1. class Deco:
    2. def __init__(self, func):
    3. self.func = func
    4. def __call__(self, *args, **kwargs):
    5. return self.func(*args, **kwargs)
    6. @Deco
    7. def foo(x, y):
    8. return x ** y
    9. # 过程拆解
    10. fn = Deco(foo)
    11. foo = fn
    12. foo(12, 34)
  • 使用场景

    • 参数、结果检查
    • 缓存、计数
    • 日志、统计
    • 权限管理
    • 重试
    • 其他
  • 例1: 写一个 timer 装饰器, 计算出被装饰函数调用一次花多长时间, 并把时间打印出来

    1. import time
    2. from functools import wraps
    3. def timer(func):
    4. @wraps(func) # 修正 docstring
    5. def wrap(*args, **kwargs):
    6. time0 = time.time()
    7. result = func(*args, **kwargs)
    8. time1 = time.time()
    9. print(time1 - time0)
    10. return result
    11. return wrap
  • 例2: 写一个 Retry 装饰器

    1. import time
    2. class retry(object):
    3. def __init__(self, max_retries=3, wait=0, exceptions=(Exception,)):
    4. self.max_retries = max_retries
    5. self.exceptions = exceptions
    6. self.wait = wait
    7. def __call__(self, func):
    8. def wrapper(*args, **kwargs):
    9. for i in range(self.max_retries + 1):
    10. try:
    11. result = func(*args, **kwargs)
    12. except self.exceptions:
    13. time.sleep(self.wait)
    14. continue
    15. else:
    16. return result
    17. return wrapper

发表评论

表情:
评论列表 (有 0 条评论,263人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Python 装饰如何使用

    装饰器(Decorator) 是 Python 里的一种特殊工具,它为我们提供了一种在函数外部修改函数的灵活能力。它有点像一顶画着独一无二 @ 符号的神奇帽子,只要将它戴在函数