1. 简述
Python的装饰器理解起来相对简单,唯一的功能就是允许程序员在不修改原有函数定义的情况下,增加函数的新功能。
装饰器本质上是一个函数,它接受一个函数作为参数并返回一个新的函数。使用装饰器可以实现很多有用的功能,比如在函数执行前后自动执行某些操作、缓存函数的返回结果、检查函数的参数类型等。
装饰器有三种不同的形式,分别是无参装饰器,被装饰函数带参数和装饰器带参数。
2. 装饰器工作原理
前面讲到,装饰器就是给一个函数增加新的功能。基本的形式如下。
def aDecorator(func):
def wrapper():
''' Do something '''
func()
''' Do something '''
return wrapper
@aAecorator
def Func():
print('hello world')
那么装饰器和被装饰函数式如何协同工作的呢?
首先我们在常规使用中,还是显示的调用Func函数,但实际的运行情况已经发生改变。由于我们的Func函数已经被添加了一个装饰器aDecorator,aDecorator中返回了一个新的函数wrapper。因此我们在调用Func的时候,实际上是执行了wrapper中的内容。
这就是装饰器的工作原理。
3. 无参装饰器
作为最简单的装饰器形式,装饰器和被装饰函数都不含有参数。示例代码如下。
def my_decorator(func):
def wrapper():
print("Pre-Process.")
func()
print("Post-Process.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
我们在调用say_hello函数时,实际上是先执行了“Pre-Process”的打印,再执行func,然后又执行了“Post-Process”的打印。
4. 被装饰函数带参
被装饰函数带参是另一种比较常见的形式。如下,这个装饰器可以适用于任何带参数的函数,因为*args和**kwargs会捕获所有传递给func的参数。
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapper
@my_decorator
def say_hello(name):
print(f"Hello {name}!")
5. 装饰器带参
当我们希望装饰器背身带有参数时,我们可以参考如下代码。如下,在这个例子中,repeat函数接收一个参数num_times,然后返回一个装饰器decorator_repeat。这个装饰器再返回实际的wrapper函数。wrapper函数会执行原函数num_times次。这种方式让装饰器更加灵活和强大。
def repeat(num_times):
def decorator_repeat(func):
@wraps(func)
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f"Hello {name}")