python装饰器

本文深入探讨了Python装饰器的概念,它用于增强函数功能,遵循开放封闭原则。装饰器本质上是闭包的语法糖,提供了一种优雅的方式在不修改原函数代码的情况下添加功能,如日志记录。文章通过实例展示了如何创建和使用装饰器,包括带参数的装饰器以及如何处理不定长参数。此外,还讨论了如何使用多个装饰器以及它们的执行顺序。
摘要由CSDN通过智能技术生成

以下是我对于python装饰器的一些个人心得,拿出来分享给大家

什么是装饰器

  • 在python中装饰器的功能是将被装饰的函数作为参数传递给与装饰器对应的函数(一般是名字相同的函数),并返回包装后的被装饰函数。
  • 装饰器的作用:增强被装饰函数的功能,做到开放封闭原则,也就是说在不修改被装饰函数源码的同时实现功能增强

本质

在我的认知中,我认为python装饰器本质上是闭包函数的语法糖,那什么是闭包函数什么是语法糖呢

闭包

闭包函数在python里就是:如果在一个内部函数里,对外部作用域但不是全局作用域的变量的引用(简而言之就是在一个嵌套函数里,内部函数去调用外部函数的局部变量(不是全局变量)),那么这个内部函数就被认为是闭包

语法糖

一种语法,不会影响原格式的功能,只是为了让程序员更方便使用,可读性更高

如何实现

假如说我们有这么一个函数

def eat():
	print("我要开始吃了")

我们想给这个函数增加一个日志功能,我们首先想到的是这样

def eat():
    print("函数调用开始")
    print("我要开始吃了!")
    print("函数调用结束")

这样看函数是不是特别臃肿,而且他入侵到原来的eat()函数里面,导致有些逻辑可能变得复杂,同时也不符合“一个函数实现一件事情”的原则

为了使得eat()增加一个日志的功能,我们可以使用装饰器来实现

def log(fun):
    def wrapper():
        print("函数开始调用")
        fun()
        print("函数调用结束")
    return wrapper

def eat():
    print("我要开始吃了!")

eat = log(eat)
eat()

在这里插入图片描述

这时候log(eat)将eat函数作为参数传递给log(),由于wrapper()函数是log()的闭包,所以他可以去调用外部函数log()的局部变量fun,也就是传递进来的eat,fun()就在返回函数wrapper()的内部执行
不过这里的eat = log(eat)看着总有些别扭,而且每一次去调用都得重复地去写,比较麻烦。
所以我们这里引用语法糖,这样看起来是不是就简洁明了啦

def log(fun):
    def wrapper():
        print("函数开始调用")
        fun()
        print("函数调用结束")
    return wrapper

@log  ##语法糖,这里等价于eat = log(eat)
def eat():
    print("我要开始吃了!")


eat()

在这里插入图片描述
不仅如此,我们还可以实现带参数的装饰器,只需要将参数扔给内部的wrapper()函数

def log(fun):
    def wrapper(name):
        print("函数开始调用")
        fun(name)
        print("函数调用结束")
    return wrapper

@log  ##语法糖,这里等价于eat = log(eat)
def eat(name):
    print("我要开始吃%s了!" % name)

eat("饺子")
eat("咸鱼")

如果传入的参数不定长,那么我们可以使用收集参数去接收

def log(fun):
    def wrapper(*args, **kwargs):
        print("函数开始调用")
        fun(*args, **kwargs)
        print("函数调用结束")
    return wrapper

多个装饰器装饰一个函数

多个装饰器执行的顺序就是从最后一个装饰器开始,执行到第一个装饰器,再执行函数本身
下面这段代码函数执行顺序:fun2() --> fun1() --> eat()

def fun1(fun):
    def wrapper():
        print("this is fun1")
        fun()
        print("fun1 end")
    return wrapper


def fun2(fun):
    def wrapper():
        print("this is fun2")
        fun()
        print("fun2 end")
    return wrapper
@fun1
@fun2
def eat():
    print("我要开始吃了!")

if __name__ == '__main__':
    eat()

在这里插入图片描述
装饰器这里手动等价于

eat = fun2(eat)
eat = fun1(eat)
eat()
--------------------------------或者------------------------------------------------
eat = fun1(fun2(eat))
eat()
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咸鱼Linux运维

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值