python中装饰器的写法

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

第一种:不带参数的函数装饰器

写一个最普通的装饰器,这种装饰器是不能传参的,只能对被装饰函数,执行固定逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def logger(func):   # func是被装饰的函数
def wrapper(*args, **kw):
print('我准备开始执行:{}函数了'.format(func.__name__))

# 被装饰的函数真正执行
func(*args, **kw)

print('函数执行完啦')
return wrapper

@logger
def add(x, y):
print('{} + {} = {}'.format(x, y, x+y))

add(200, 50)

第二种:带参数的函数装饰器

写一个能传参的装饰器,可以根据不同的场景进行调整。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import time

def logger(tt):
def wrapper1(func): # 第一层接收被装饰函数
def wrapper2(*args, **kw): # 第二层实现装饰逻辑
print('我在{}时刻开始执行:{}函数了'.format(tt, func.__name__))

# 被装饰的函数真正执行
func(*args, **kw)

print('在{}时刻函数执行完啦'.format(time.time()))
return wrapper2
return wrapper1

@logger(time.time())
def add(x, y):
print('{} + {} = {}'.format(x, y, x+y))

add(200, 50)

第三种:不带参数的类装饰器

基于类的装饰器,必须实现init和call两个内置函数,前者用于接收被装饰函数,后者用于实现装饰逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
class logger(object):
def __init__(self, func):
self.func = func

def __call__(self, *args, **kwargs):
print('[INFO]: the function {func}() is running...'.format(func=self.func.__name__))
return self.func(*args, **kwargs)

@logger
def add(x, y):
print('{} + {} = {}'.format(x, y, x+y))

add(200, 50)

第四种:带参数的类装饰器

带参数的类装饰器和不带参数的类装饰器有很大不同,init不再接收被装饰函数而是接收传入参数,call既接收被装饰函数又要实现装饰逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class logger(object):
def __init__(self, level='INFO'):
self.level = level

def __call__(self, func): # 接收被装饰函数
def wrapper(*args, **kwargs):
print('[{level}]: the function {func}() is running...'.format(level=self.level, func=func.__name__))
func(*args, **kwargs)
return wrapper

@logger(level='WARNING')
def add(x, y):
print('{} + {} = {}'.format(x, y, x+y))

add(200, 50)