Python装饰器:为函数添加额外的功能
Python装饰器是Python语言的重要特性之一,可以为函数添加额外的功能而不影响函数的原有结构。装饰器本质上是一个函数,它接受被装饰函数作为参数,以实现在函数运行前、运行中或运行后扩展功能的目的。在本文中,我们将介绍Python装饰器的基础知识和使用方法。
1.什么是装饰器
Python中的装饰器相当于外部包裹一个函数,可以把其本身不想做甚至不知道该做的事情交给装饰器函数来完成,而函数依旧保持原有的结构和功能。这个过程就像是将一个函数包裹在另一个函数中,并在函数的外部对它进行处理。
示例代码:
def func1():
print("function 1")
def func2(func):
print("function 2")
func()
print("function 3")
func2(func1)
这段代码中,函数func2的参数是函数func1,在函数func2中,我们可以添加我们想要的任何附加功能。在这个例子中,我们给函数func1添加了上下文输出。
运行结果:
function 2 function 1 function 3
这样的示例代码显然是可行的,但却产生了一些问题。在示例代码中,我们需要在函数func2中手动调用被装饰函数,这导致了代码冗余和可读性差的问题。这就是Python装饰器要解决的问题。
2.使用装饰器
Python装饰器就是为了解决示例代码中出现的问题而创造的。装饰器就是一个函数,它接受一个函数为参数,并在内部包裹该函数以实现功能扩展的目的。因此,我们可以将示例代码改写为以下形式:
def decorator(func):
def wrapper():
print("function 2")
func()
print("function 3")
return wrapper
@decorator
def func1():
print("function 1")
func1()
运行结果:
function 2 function 1 function 3
这段代码中,我们将原有参数为func的函数decorator作为装饰器函数,用一个新的函数wrapper包裹原有的函数func1。在wrapper函数内部,我们可以添加我们想要的任何附加功能。在这个例子中,我们给函数func1添加了上下文输出。通过@decorator将装饰器函数与被装饰函数联系在一起,就可以实现自动调用装饰器函数的目的。
3.装饰器的类型
Python装饰器有多种类型,包括函数装饰器、类装饰器、装饰器函数等。我们将逐步介绍每一种装饰器并给出示例代码。
- 函数装饰器
函数装饰器是Python中经常被使用的装饰器类型。函数装饰器指的是传入一个函数,返回一个函数,通常用于在函数调用前进行预处理或调用后进行结果的处理。函数装饰器的形式如下所示:
def decorator(func):
def wrapper(*args, **kwargs):
# do something before the function
result = func(*args, **kwargs)
# do something after the function
return result
return wrapper
在这个例子中,我们给函数func添加了一个‘前缀’和一个‘后缀’,并在返回值结果中加入了一个字符串。这个字符串将在函数调用后打印出来。可以看到,装饰器的重点是在定义内部的wrapper函数上,通过封装函数实现了对原函数的增强。
- 类装饰器
类装饰器是一种比较高级的技术,通常用于处理类的定义。类装饰器的形式如下所示:
class Decorator:
def __init__(self, cls):
self.cls = cls
def __call__(self, *args, **kwargs):
obj = self.cls(*args, **kwargs)
obj.attr = 'hello'
return obj
@Decorator
class MyClass:
pass
print(MyClass().attr)
在这个例子中,我们定义了一个装饰器类Decorator,它接受一个类作为参数,在调用之前添加一个新的属性。在声明类时,通过@Decorator来调用装饰器类,将该类直接传递给Decorator类的初始化函数。
- 装饰器函数
装饰器函数指的是返回一个装饰器函数的函数。我们可以通过定义返回装饰器函数的函数来实现更加灵活的装饰器。当需要对一个函数应用不同的装饰器时,这种方法非常有用。装饰器函数的形式如下所示:
def decorator_maker(arg1, arg2):
def decorator(func):
def wrapper(*args, **kwargs):
# do something before the function
result = func(*args, **kwargs)
# do something after the function
return result
return wrapper
return decorator
@decorator_maker('arg1', 'arg2')
def func():
pass
在这个例子中,我们定义了一个返回装饰器函数的函数decorator_maker,它接受两个参数arg1和arg2。在返回的装饰器函数中,我们为函数添加了一个‘前缀’和一个‘后缀’,并在调用返回值之前打印了一段信息。在声明函数时,我们通过@decorator_maker('arg1', 'arg2')将参数传递给装饰器函数。
4.装饰器应用实例
在实际应用中,Python装饰器可以帮助我们实现很多功能,比如验证用户身份、计算函数执行时间等。以下是几个装饰器的应用实例:
- 登录验证
def login_required(func):
def wrapper(request,*args,**kwargs):
if not request.user.is_authenticated:
# redirect to login page
return redirect('login')
return func(request, *args, **kwargs)
return wrapper
@login_required
def my_view(request):
return HttpResponse('ok')
在这个例子中,我们引入了一个login_required的装饰器,它用于验证用户是否已经登录。如果用户未登录,将被重新定向到登录页面。在my_view函数声明前添加了@login_required装饰器,将会验证用户是否通过登录验证后才能访问该页面。
- 计算函数执行时间
import time
def time_it(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print('time cost: {}'.format(end - start))
return result
return wrapper
@time_it
def my_function(*args, **kwargs):
# do something
pass
在这个例子中,我们定义了一个装饰器函数time_it,它可以计算函数执行的时间。在声明函数时,我们通过@time_it将函数放在装饰器函数下面,来调用装饰器函数。
5.总结
Python装饰器是Python语言的重要特性之一,可以为函数添加额外的功能而不影响函数的原有结构。Python语言中的装
