装饰器是python当中的进阶用法,并且应用非常广泛,但是在实际的工作过程中,我发现很多人常常因为觉得装饰器很复杂,望而生畏。实际上从原理来讲并不难。
这一节,我会从函数为切入点,引出装饰器的概念和基本用法,最后再结合我们的数据自动化程序,这个实际的例子,让大家能够使数据自动化程序功能更加的完善,并且学会装饰器的用法,先来看一下,最终钉钉报警的效果:
钉钉报警效果
1、函数核心知识点
第一点:函数可以作为对象,赋予给变量
函数作为对象
这里把func这个函数,赋值给了send_message,所以最终当执行send_message的时候,就相当于执行了func()这个函数。
第二点:函数可以作为参数,传递到另一个函数当中
函数作为参数
root_call这个函数当中,第一个参数是一个函数,调用root_call的时候,传入了get_message这个函数,然后把message这个参数,传递给get_message。
第三点:函数里可以嵌套函数
函数的嵌套
我们先看func( )这个函数,它最终return的是get_message()这个函数,当程序执行到这里时,就会回去调用get_message,从而完成函数的嵌套。
第四点:函数的返回值也可以是函数
函数作为返回值
这里,函数 func_closure() 的返回值是函数对象 get_message 本身,之后,我们将其赋予变量 send_message,再调用 send_message(‘hello world’),最后输出了'Got a message: hello world'。
2、装饰器的基础知识
如果以上函数的知识大家都能看明白的话,那么学习接下来的装饰器将会非常轻松,
我们先来看一个最简单的例子:
这段代码中,my_dacorator函数当中嵌套了wrapper函数,wrapper函数当中又包含了作为参数传递进来的func()函数,其实最终的目的,是在执行func函数之前,先执行wrapper当中的部分,并不改变func函数的执行过程,所以,my_decorator这个函数仅仅对greet增加了一层装饰作用。
实际上,在python当中有更加优雅的写法,就是要讲的装饰器,用装饰器的写法如下:
这段代码和之前的代码具有相同的功能,并且非常的简洁,@my_decorator就相当于前面的greet=my_decorator(greet)语句,这样写还有一个好处,就是如果其他函数也想用my_decorator装饰,那只需要把@my_decorator加在函数的上面就可以了。
如果所装饰的目标函数是带有参数的,那么只需要加到wrapper()函数当中就可以了,前面我们也讲过,使用*args和**kwargs可以代表任何参数,所以我们只需要写成下面的样子:
带有参数的装饰器
关于装饰器的基础部分,今天就先给大家讲这些,详细的内容,我会在视频课程当中为大家讲解。
3、实战案例:用装饰器监控程序执行,并把错误发送到钉钉报警
学完了装饰器的基础,我们就把装饰器用在项目上。首先在utils文件夹下面创建一个py文件,我这里命名为mysql_error:
话不多少,先上代码:
装饰器函数
这个装饰器,用到的就是上面讲的知识点,唯一一个没有讲到的是@functools.wraps(func)方法,因为每个装饰器会在很多地方用到,装饰器装饰过的函数,其原有的基本信息会被改变,比如说函数名称等,都会变成装饰器的信息,这样的话,如果程序出现错误,我们也不到是哪个被装饰的函数出现了错误,不便于排查,加上@functools.wraps(func),可以保持被装饰函数信息不变。func_name = func.__name__就是获取被装饰函数名称,
我还用到了一个方法字符串处理方法 StringHelp.error(error_str),这个是我自定义的方法,详细如下:
报错字符串处理模块
模块的功能已经给大家标注了,有不理解的同学欢迎留言讨论。
最后,把写好的装饰器应用在get_df函数上:
给数据查询函数加上装饰器
还记得我们上节课的数据获取功能吗,这里我故意把SQL写错,看一下效果:
来看下运行效果:
钉钉完成报警
这样钉钉就完成了报警功能,如果线上出问题的话,我们就能第一时间定位错误,解决问题,如果大家按照这样做的话,那么可想而至,等待你的将会是升职加薪。