Python Decorator

Python Decotator

decorator

装饰器(decorators)是 Python 中的一种高级功能,它允许你动态地修改函数或类的行为。

装饰器是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。

装饰器的语法使用 @decorator_name 来应用在函数或方法上。

Python 还提供了一些内置的装饰器,比如 @staticmethod@classmethod,用于定义静态方法和类方法。

装饰器的应用场景:

  • 日志记录: 装饰器可用于记录函数的调用信息、参数和返回值。
  • 性能分析: 可以使用装饰器来测量函数的执行时间。
  • 权限控制: 装饰器可用于限制对某些函数的访问权限。
  • 缓存: 装饰器可用于实现函数结果的缓存,以提高性能。

我们先看下面这个例子,我们对hello()进行一些包装,实现一个记录函数运行时间的方法。

1
2
3
4
5
6
7
def timing(f):
return f

def hello():
print("Hello World")
hello = timing(hello)
hello()

上面的这个例子我们调用timing,实际上返回的还是hello这个函数的,其实什么都没有做。在实际业务中,我们希望timing返回一个新的函数,调用新函数就相当于调用了hello,开发中习惯叫这个新函数wrapper。

1
2
3
4
5
6
7
8
9
10
11
12
def timing(f):
def wrapper():
return f
return wrapper

def hello():
print("Hello World")

hello = timing(hello)
# 我们在这里print hello 实际上已经指向wrapper
print(hello)
hello()

我们简单实现以下函数计时器的逻辑

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

def timing(f):
def wrapper():
start_time = time.time()
result = f()
end_time = time.time()
print(f"Total time => {end_time - start_time}")
return result

return wrapper

def hello():
print("Hello World")

hello = timing(hello)
hello()

到此实际上我们已经实现了装饰器的功能,但这种写法有点奇怪,我们可以使用Python的语法糖来实现

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

def timing(f):
def wrapper():
start_time = time.time()
result = f()
end_time = time.time()
print(f"Total time => {end_time - start_time}")
return result

return wrapper

@timing
def hello():
print("Hello World")

hello()
装饰器的参数处理

上面的例子是没有参数的情况,正常的业务处理中我们会面对各种各样的参数。

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

def timing(f):
def wrapper(*args, **kwargs):
start_time = time.time()
result = f(*args, **kwargs)
end_time = time.time()
print(f"Total time => {end_time - start_time}")
return result

return wrapper

@timing
def hello():
print("Hello World")

@timing
def hello_one(name):
print(f"Hello, {name}")

hello()
hello_one("John", "Tom")

我们可以在wrapper上加入可变参数,这样就可以适配所有的参数场景。

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


def timing(f):
def wrapper(*args, **kwargs):
start_time = time.time()
result = f(*args, **kwargs)
end_time = time.time()
print(f"Total time => {end_time - start_time}")
return result

return wrapper


@timing
class Foo:
def __init__(self):
pass


Foo()

上面的代码创建 Foo() 实例时,装饰器 @timing 会记录类的构造函数执行所需的时间。因此,打印出来的时间表示了调用 Foo() 实例化对象的时间消耗。


Python Decorator
https://skynetboys.github.io/2024/08/03/Python-Decorator/
Author
Edison
Posted on
August 3, 2024
Licensed under