Python编程:装饰器

前言

当时是这样写的:在自定义一个函数时,用了进行修饰。如下:

要想彻底搞懂Python中的装饰器,除了需要有一点Python中的函数基础,还需要解决如下四个问题。当我们解决了这四个问题后,也就彻底搞懂Python中的装饰器。

1.什么是装饰器,其本质是什么

2.装饰器有什么作用?

3.装饰器有什么使用特点(使用原则)?

4.装饰器的应用场景

装饰器

我们按照上面提的四个问题,通过寻找问题答案一一剖析这个装饰器。如下就是一个自定义的打印函数日志的装饰器,先来大概看下其定义样式。

1.什么是装饰器,其本质是什么

Python中的装饰器并没有什么神秘的,其本质上就是个函数。可以用一个等式理解:

知道为什么一再提示如果你还不知道Python中的函数,请先了解函数后,再来学习装饰器了吧。

关于Python中,什么是函数、函数的本质、函数的参数等一系列内容,可参考本系列的

《Python中的函数》

2.装饰器有什么作用?

装饰器,说白了就是用来增强其他函数功能的函数。其形式,通常是在被修饰函数定义时,用修饰。

例如:

这里的,我自定义了一个计算一个数平方的函数,要求调用这个函数时打印其调用日志,就可以写一个日志装饰器,假设命名为,用来装饰所要调用的函数。

装饰器的定义如上面。

3.装饰器有什么使用特点(使用原则)?

·1.不会修改被装饰的函数的源代码。

(对函数的源代码没有任何修改,只是在原来功能的基础上额外增强函数的功能。)

·2.不会改变被装饰函数的调用方式。

(原来怎么调用,被装饰后依旧怎么调用。)

·3.不会改变被装饰函数的返回结果。

这三点使用特点非常重要,归结为:原来的函数之前怎么调用、怎么入参、什么样的返回值,使用装饰器装饰后这些都不受任何影响。也就是:我们在不对原来函数的源代码、调用形式、返回值等任何修改的情况下,增强了原来函数的功能。

4.装饰器的应用场景

应用场景非常多,开发中常见的如:

1.插入日志

2.性能测试

3.处理事务

4.开发python开源框架时,非常常用

示例

有了以上认识,我们看一个完整的示例:

需求1:打印出一个函数调用的日志信息,比如被调用的函数名、调用时刻等。

方案一:修改函数源代码,我们可以在定义时就写入打印出一个函数调用的日志信息。【极不推荐】

不推荐理由:如果一个项目中,已有成千上万个函数、方法,累到吐血不说,还修改了原函数的源码。

方案二:使用装饰器。【推荐】

运行结果,如果在定义函数时,没有加装饰器,则就是前面我们之前最常用的函数调用。现在我们用了装饰器,打印结果就有了日志。现在运行结果如下:

说明:

1.在定义装饰器时,入参传入了一个函数,所以装饰器是一个高阶函数,也返回了一个内层函数名。

2.特别提醒: 外层函数的返回结果是嵌套函数函数名,而不是返回。这两个是不同的概念哦。

3.嵌套函数中的内层函数,函数名可以是任何符合Python命名规则的标识符。我这里命名,你可以自定义为其他合法的函数名。

4.为了保证原函数的调用入参不受任何影响,内层函数入参:。

5.为了保证原函数的返回值不受任何影响,我们用一个临时变量接收,并在内层函数进行返回了。

6.你还记得前面提到的装饰器的本质吗?

其本质上就是个函数。可以用一个等式理解:。

多个装饰器函数名问题

需求2:在打印函数调用日志基础上,打印出函数的运行耗时时间。

为了让函数有耗时操作,我们在函数内。调用函数,计算5的平方,运行结果:

说明:

1.我们在函数定义时,用了两个装饰器进行装饰,打印函数调用日志、计算函数运行耗时。

2.运行结果中,,为什么是方法呢?

这是因为我们用了两个装饰器,层层装饰过程中,先拿到的是传入的,第二个装饰器拿到的是第一个装饰器的内层函数的函数名。拿到这样的函数名,如果有些依赖函数签名的代码执行就会出错。

3.怎么样才能拿到正确的函数名呢?打印方法名都是:。

用,不需要在装饰器函数中编写这样的代码,因为Python内置的装饰器就是干这个事的,所以,一个完整的的写法如下:

两个装饰都这么修改后,打印结果如下:

现在,只需在定义的前面加上即可。此时,符合我们需求了。

装饰器进阶:带参数的装饰器

需求3:现要求可以自定义的打印日志。

方案:这就需要在装饰器基础上,外面再嵌套一层函数,接收自定义传入的参数,即三层函数嵌套。代码如下:

运行结果:

小结

本文学习Python中的装饰器,另外又学习了装饰器进阶知识:可以传入参数的装饰器、多装饰器中函数名的问题的处理等。学习此知识,除了需要有一点Python中的函数基础,还需要解决文中提到的四个问题。当我们解决了这四个问题后,也就彻底搞懂Python中的装饰器了。

装饰器思维导图截图如下:

装饰器笔记截图

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180818G1I2AI00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券