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}")
04-03 08:10