Python中的装饰器:简介以及应用

装饰器本质上是一个 Python 函数,它可以让其他函数在不需要做任何代码变动的情况下增加额外功能。装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器和注解的区别在于,注解只是给函数加上一个标记,在执行的时借会进行处理。而装饰器在加载时就完成了装饰。

一、基础的装饰器

在 Python 中,我们可以通过定义一个接受函数对象作为参数并返回一个新函数的函数来创建装饰器。让我们通过一个简单的例子来理解装饰器的工作原理:

“`python
def my_decorator(func):
def wrapper():
print(“Something is happening before the function is called.”)
func()
print(“Something is happening after the function is called.”)
return wrapper

@my_decorator
def say_hello():
print(“Hello!”)

say_hello()
“`

在上述代码中,最后一行的`say_hello()`实际上调用的是`wrapper()`函数。`@my_decorator`是一种方便的语法糖,它相当于`say_hello = my_decorator(say_hello)`。

二、装饰器中传递参数

在很多情况下,我们需要向被装饰的函数传递参数。为了实现这一点,我们可以在内层函数`wrapper`中接受任意数量的参数,然后将这些参数传递给被装饰的函数。

“`python
def my_decorator(func):
def wrapper(*args, **kwargs):
print(‘Before call’)
result = func(*args, **kwargs)
print(‘After call’)
return result
return wrapper

@my_decorator
def add(a, b):
return a + b

print(add(1, 3)) # 结果为4
“`

这里,`*args`和`**kwargs`分别表示位置参数和关键字参数。

三、保留函数元信息

在使用装饰器后,我们可能会发现函数的元信息已经改变。如,函数的文档字符串(docstring)和名字就不再是原来的了。这时,我们可以使用内置的`functools.wraps`装饰器来保留函数的元信息。

“`python
from functools import wraps

def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(‘Before call’)
result = func(*args, **kwargs)
print(‘After call’)
return result
return wrapper

@my_decorator
def add(a, b): “””Adds two numbers”””
return a + b

print(add.__name__) # 结果为’add’
print(add.__doc__) # 结果为’Adds two numbers’
“`

四、类装饰器

除了函数,Python 也允许我们使用类来作为装饰器。类装饰器依赖于函数__call__(),每当你调用装饰器时,它会调用该方法。

“`python
class myDecorator(object):
def __init__(self, f):
self.f = f
def __call__(self, *args, **kwargs):
print(“Before call”)
self.f(*args, **kwargs)
print(“After call”)

@myDecorator
def myfunc(a, b):
print(“inside myfunc()”)
return a + b

myfunc(1, 2)
“`

Python的装饰器功能是一个强大且有用的工具,可以修改函数的行为或者为函数添加功能。但要注意装饰器的执行顺序和使用范围以及不能滥用装饰器,从而保证代码的简洁与可读性。


已发布

分类

来自

标签:

评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注