python使用class实现一个装饰器

简介

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

常见的装饰器

日常开发中也有不少使用装饰器,比如下面的retry重试的代码就是一个装饰器,可以再不改变我们业务代码的情况下使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from retry import retry
def retry(exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0, logger=logging_logger):
"""Returns a retry decorator.
:param exceptions: an exception or a tuple of exceptions to catch. default: Exception.
:param tries: the maximum number of attempts. default: -1 (infinite).
:param delay: initial delay between attempts. default: 0.
:param max_delay: the maximum value of delay. default: None (no limit).
:param backoff: multiplier applied to delay between attempts. default: 1 (no backoff).
:param jitter: extra seconds added to delay between attempts. default: 0.
fixed if a number, random if a range tuple (min, max)
:param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
default: retry.logging_logger. if None, logging is disabled.
:returns: a retry decorator.
"""
@decorator
def retry_decorator(f, *fargs, **fkwargs):
args = fargs if fargs else list()
kwargs = fkwargs if fkwargs else dict()
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter,
logger)
return retry_decorator

使用class实现装饰器

主要是通过class中的 __call__魔法方法来实现
通过类我们可以将比较复杂的逻辑拆解到函数中实现,如果有特殊的需求我们也只需要继承该类对某个函数进行修改即可

不带参数的装饰器类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Demo(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("hello")
return self.func(*args, **kwargs)
@Demo
def hello(name):
print(name)
hello("word")

带参数的装饰器类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# coding:utf-8
class Demo(object):
def __init__(self, debug: bool = False):
self.debug = debug
def __call__(self, func):
print(f"debug: {self.debug}")
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@Demo(debug=True)
def hello(name):
print(f"hello {name}")
hello("word")

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器