前言
本文继续来介绍Python有关装饰器的内容。前面有关装饰器的介绍,详情请查看这里:
Python编程:装饰器和函数之关系?
Python编程:装饰器之底层逻辑与实现?
Python编程:如何处理带参装饰器和通用装饰器 ?
本文将带领读者朋友搞定装饰器是如何修改函数名称以及如何实现链式装饰器。
封面图
改变函数名称
当使用装饰器时,有个重点要牢记:在你装饰某个函数后,其函数名将会被改变。别急着说这怎么可能呢?通过下面的示例来观察一下:
输出结果:
没用装饰器前函数名称: lastName
输出结果:
使用装饰器后的函数名称: wrapper
注意,我们这里用的还是前一个示例中的装饰器和函数。运行上述代码——带装饰器和没有装饰器的两种情况,通过对结果的对比,很清楚知道了函数名称被修改:没有装饰器的函数名和定义时相同,而有装饰器的函数名被修改为wrapper了。
为什么名称从“lastName”改为“wrapper”了呢?因为当我们装饰它时,装饰器函数返回了wrapper函数。记住,装饰器与这一行代码功能完全相同:
lastName = upperDecorator(lastName)
我们将装饰器的返回值重新赋值给函数。因为装饰器只是返回wrapper函数,所以原始函数的名称更改为现在“wrapper”了。
为了解决这个问题,Python提供了一个非常简单的解决方案,即functools模块。让我们看看如何使用这个模块来保持原来的函数名不变:
在上述代码中,我们使用了functools.wraps()方法,其本身就是一个装饰器。所以,我们用@符号来在wrapper函数上使用它。这是使用语法:@functools.wraps(func)。原始函数(func)是该方法的参数。这个方法保留了原始函数的信息。现在,让我们再一次打印lastName函数的名称(不带装饰器和带装饰器的代码和前面的相同,这里仅观察带装饰器的输出):
输出结果为:
使用装饰器后的函数名称: lastName
很显然,通过使用Python提供的解决方法,实现了方法名的不变。这里主要掌握住应用Python提供的解决方案的规则,即导入functools模块、应用wraps方法装饰定义装饰器的包装器方法。
链式装饰器
大多数时候,我们需要为某个函数使用多个装饰器。这被称为相同函数的链式装饰器(chaining decorators)。来看看如何使用多个装饰器(或相同的装饰器多次使用)。
上面的清单中,定义了两个装饰器。每个函数在调用原始函数之前和之后都输出一个不同的符号。现在我们把它们都用在同一个函数上:
运行程序结果如下:
我们在sayHi()函数上接连用三个装饰器(多次使用)。在输出中,可以看到装饰器的执行顺序。更接近函数定义的装饰器函数会先于其他函数执行。
现在让我们把装饰器的顺序颠倒一下,再看一次输出:
输出结果如下:
正如输出所示,当我们改变装饰器的顺序时,执行顺序也会发生变化。
这个示例,主要介绍如何使用多个装饰器或链式装饰器,并掌握装饰的执行顺序问题,以便在实际编程中更好地控制装饰目的。
小结
本文主要介绍了装饰器为什么改变了所装饰的函数名称的?以及如何保持函数名的不被改变的解决方案?还介绍了Python中所谓的“链式装饰”的实现。相应内容结合代码更容易理解。
本文就介绍这些了。
最后,请各位朋友点个赞、转发分享出去吧,以帮助更多的Python爱好者,谢谢