一篇文章读懂Python装饰器

59 篇文章 1 订阅
37 篇文章 0 订阅

欢迎关注微信公众号“Python小灶,和我一起每天学习Python新知识”
不积跬步,无以至千里;不积小流,无以成江海。每天进步一点点,也是很大的进步。
在这里插入图片描述





一、什么是装饰器

在这里插入图片描述
这是我从官方文档接下来的图,虽然现在官方文档已经有中文版了,但是众所周知,中文文档是需要翻译的。



二、别给老夫讲原理,老夫写代码就是一把梭

观众老爷可能不满了,这都是啥,还是不明白。
别急,下面举两个简单的栗子就明白了。
简单来讲,装饰器就是在不改变原有代码结构的基础上,添加新功能。
示例:现在想在打印“Hello World”之前想再打印个"Hello Python"

def fun():
    print("Hello World")


if __name__ == "__main__":
    fun()

这个例子可能举的不是太好,可能比较机智的同学已经忍不住冷笑了。

def fun():
    print("Hello World")


if __name__ == "__main__":
    print("Hello Python")
    fun()

当然,你知道我不是这个意思,所以我们来个实际点的例子:
(当函数多、功能复杂的时候,上面那个方法不好使,特别容易污染工程代码,而且我这是举的最简单的例子,大部分函数是为了实现某一功能,是比较复杂的)
想在要在每一个函数的开头和结尾分别加上:这是函数XX的开头以及这是函数XX的结尾

def fun1():
    print("这是函数{}的主体".format(fun1.__name__))


def fun2():
    print("这是函数{}的主体".format(fun2.__name__))


if __name__ == "__main__":
    fun1()
    fun2()

# 这是函数fun1的主体
# 这是函数fun2的主体

那么如何实现

def a_decorator(fun):
    def wrapTheFunction():
        print("这是函数{}的开头".format(fun.__name__))
        fun()
        print("这是函数{}的结尾".format(fun.__name__))

    return wrapTheFunction


@a_decorator
def fun1():
    print("这是函数{}的主体".format(fun1.__name__))


@a_decorator
def fun2():
    print("这是函数{}的主体".format(fun2.__name__))


if __name__ == "__main__":
    fun1()
    fun2()

# 这是函数fun1的开头
# 这是函数wrapTheFunction的主体
# 这是函数fun1的结尾
# 这是函数fun2的开头
# 这是函数wrapTheFunction的主体
# 这是函数fun2的结尾

恭喜,你已经学会了装饰器,当然你可能发现了一点问题,就是打印不太对劲,这里的函数被warpTheFunction替代了。它重写了我们函数的名字和注释文档(docstring)。我举得例子因为刚好用到函数名,其实如果不需要用到函数名的装饰器不需要关注这个,如果一定要用到,解决办法就是那就是 functools.wraps

from functools import wraps


def a_decorator(fun):
    @wraps(fun)
    def wrapTheFunction():
        print("这是函数{}的开头".format(fun.__name__))
        fun()
        print("这是函数{}的结尾".format(fun.__name__))

    return wrapTheFunction


@a_decorator
def fun1():
    print("这是函数{}的主体".format(fun1.__name__))


@a_decorator
def fun2():
    print("这是函数{}的主体".format(fun2.__name__))


if __name__ == "__main__":
    fun1()
    fun2()


# 这是函数fun1的开头
# 这是函数fun1的主体
# 这是函数fun1的结尾
# 这是函数fun2的开头
# 这是函数fun2的主体
# 这是函数fun2的结尾

怎么样,是不是简单又有趣又实用,你学废了吗?



三、知其然,也想知其所以然

接下来我就给各位观众老爷翻译翻译,什么叫装饰器。

  • 装饰器是一个函数;
  • 函数都有返回值,装饰器的返回值也是函数;
  • 装饰器语法是一种语法糖(一种封装)。


    怎么来理解上述内容?,还是以上面示例为例。
    在Python中,一切皆是对象,变量是,函数也是,所以函数可以作为参数传递,也可以当成返回值。
    带着这个认知,我们去看看装饰器发生了什么(顺序1234)。

# 2、函数走到这里,a_decorator里定义了wrapTheFunction
# 但是只是定义,没有调用,整个a_decorator返回wrapTheFunction
def a_decorator(fun):
    def wrapTheFunction():
        print("Hello Python")
        fun()

    return wrapTheFunction


def fun():
    print("Hello World")


# 1、调用a_decorator函数,并把fun作为参数传给它
# 注意,不能加(),否则直接就执行了
fun = a_decorator(fun)  # 3、把调用的结果wrapTheFunction赋值给fun
if __name__ == "__main__":
    fun()  # 4、fun()此时就等于运行 wrapTheFunction()

# Hello Python
# Hello World

把上述代码封装成如下形式,就是装饰器。

@a_decorator
def fun():
    print("Hello World")
    
if __name__ == "__main__":
    fun()

可能有些人对fun和fun()很困惑,其实很好理解,fun是指这个函数,fun()是指这个函数调用的结果。




四、进阶,带参数的装饰器

待补充



五、参考文献,资料

想了解的更详细,去看以下两篇文档哦。
Python进阶_装饰器
菜鸟教程_装饰器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值