# Python 装饰器:给函数统一添加执行前后提示

最近我有一个想法:  
想在每个函数执行之前打印一句 **“开始执行”**,在函数执行结束之后再打印一句 **“执行结束”**。

比如现在有多个函数:

```python
def fun1():
    print("我是函数1")

def fun2():
    print("我是函数2")

def fun3():
    print("我是函数3")

如果我直接给每一个函数都手动加上打印语句,就会变成这样:

def fun1():
    print("开始执行")
    print("我是函数1")
    print("执行结束")

def fun2():
    print("开始执行")
    print("我是函数2")
    print("执行结束")

def fun3():
    print("开始执行")
    print("我是函数3")
    print("执行结束")

这样写虽然可以实现效果,但是代码会变得很重复。
如果函数越来越多,每个函数都要手动加一遍,就会很麻烦,也不方便后期维护。

所以,我们可以使用 Python 里的 装饰器 来解决这个问题。

一、什么是装饰器

装饰器的作用就是:
在不修改原函数内部代码的情况下,给函数额外增加一些功能。

比如这里,我不想改 fun1fun2fun3 里面原本的代码,但是我又想让它们在执行前后自动打印内容。

这时候就可以写一个装饰器函数。

二、定义装饰器函数

代码如下:

def outer(origin):
    def inner(*args, **kwargs):
        print("开始执行")
        res = origin(*args, **kwargs)
        print("执行结束")
        return res
    return inner

这里的 outer 就是一个装饰器函数。

它接收一个参数 origin,这个参数代表原来的函数。

outer 函数里面,又定义了一个 inner 函数。
真正执行的时候,其实执行的是 inner

执行流程是:

  1. 先打印 "开始执行"
  2. 再执行原来的函数 origin
  3. 然后打印 "执行结束"
  4. 最后把原函数的返回值返回出去

这里使用了:

*args, **kwargs

是为了让这个装饰器可以适配不同参数的函数。
不管原函数有没有参数、有几个参数,都可以正常接收。

三、使用装饰器

有了装饰器之后,就可以这样使用:

@outer
def fun1():
    print("我是函数1")
    value = 1
    return value

这里的:

@outer

其实等价于:

fun1 = outer(fun1)

也就是说,原来的 fun1 函数被传进了 outer,然后 outer 返回了一个新的 inner 函数。

所以之后再调用 fun1() 的时候,执行的就不是原来的函数本身,而是经过装饰器包装后的函数。

四、完整代码

def outer(origin):
    def inner(*args, **kwargs):
        print("开始执行")
        res = origin(*args, **kwargs)
        print("执行结束")
        return res
    return inner


@outer
def fun1():
    print("我是函数1")
    value = 1
    return value


@outer
def fun2():
    print("我是函数2")
    value = 2
    return value


@outer
def fun3():
    print("我是函数3")
    value = 3
    return value


fun1()
fun2()
fun3()

五、运行结果

执行代码后,输出结果是:

开始执行
我是函数1
执行结束
开始执行
我是函数2
执行结束
开始执行
我是函数3
执行结束

可以看到,每个函数在执行之前都会自动打印:

开始执行

执行完函数之后,又会自动打印:

执行结束

而我们并没有在每个函数内部重复写这些代码。

六、装饰器的好处

使用装饰器之后,代码会更加简洁。

它的好处主要有:

  1. 不需要修改原函数内部代码
  2. 可以统一给多个函数添加相同功能
  3. 减少重复代码
  4. 后期维护更加方便

比如以后我不想打印 "开始执行""执行结束" 了,只需要改装饰器里面的代码就可以,不需要一个函数一个函数去改。

七、总结

这段代码主要体现了 Python 装饰器的基本用法。

装饰器可以理解为:
给原来的函数外面再包一层新的功能。

原函数负责做自己的事情,装饰器负责在函数执行前后添加额外逻辑。

在这个例子中,原函数只负责打印自己是谁,而装饰器统一负责打印:

开始执行
执行结束

这样代码既清晰,又减少了重复内容。

这就是装饰器最常见的使用场景之一。

更多推荐