Python高阶函数装饰器

简介: Python高阶函数装饰器

“ 从CANoe vTESTstudio版本7开始,支持使用python编辑器编写python脚本。其中CANoe提供了许多API接口给python使用,大大扩展了python的可用性。在python中使用装饰器定义capl中的事件处理程序(on key/on timer等)。对此我们有必要了解什么是装饰器”

装饰器,装饰是包装的意思,器表示工具。所以装饰器字面意思指的是包装用的工具。就像是买的礼物外面的包装盒子一样

可以看出,装饰器有三个特点:

不能改变礼物的本身
包装盒和礼物是一起的
拿出礼物时只会说礼物的名字,不会说包装盒的名称
“ 我们以给别人买生日蛋糕为例,你让服务员给蛋糕包装时,肯定不能让包装盒破坏蛋糕本身;你每次把蛋糕拿出来给别人看时,包装盒必定和蛋糕是一起拿出来的;当你拿出蛋糕时,只会介绍说这是蛋糕,并不会说这是我买的蛋糕和包装盒,对吧!”

那么在python中蛋糕和包装盒分别表示什么呢?蛋糕就是python函数,包装盒就是装饰器

所以,装饰器的特定是:

不能改变函数的内部代码
调用函数时装饰器一并调用
使用函数名调用函数
我们定义一个函数并运行:

def func1():
print("run func1")

func1()
打印的结果为:run func1

现在我想给它添加点特色,就是在打印“run func1”前先打印“program start”。有人说那我把func1函数体改成这样:

def func1():
print("program start")
print("run func1")

func1()
但是如此一来,就破坏了函数func1的函数体,这肯定不是装饰器的作用

那这样呢?

def func1():
print("run func1")

print("program start")
func1()
这样也不符合调用函数func1时一并调用装饰器,因为上面的代码实际上调用了print("program start")和func1(),肯定也不是装饰器的作用

那我利用函数的可参数化呢?

def func1():
print("run func1")

def prog1(func):
print("program start")
func()

prog1(func1)
这样使用的是其他函数调用的,也不符合装饰器的特点

分析:不能改变函数func1的结构,肯定得把函数func1当作参数传入另一个函数prog1中,在另一个函数中实现在调用func1前调用print("program start")。但是又不能通过调用prog1实现,还是要调用func1。怎么办?可以把prog1赋值给func1,以此实现调用func1即是调用prog1

下面这样可以吗?

def func1():
print("run func1")

def prog1(func):
print("program start")
func()

func1 = prog1(func1)

func1()
运行脚本后你会发现报错,报错内容如下:

出问题的点在哪呢?就在func1 = prog1(func1),当把调用prog1(func1)返回的对象赋值给func1时,调用prog1(func1)其实并没有返回值。那么func1就变成了None,最后调用func1肯定就报错了

所以需要在函数prog1的函数体内return一个对象,这个对象需要赋值给func1。由于func1是函数指针,那么prog1 return的对象也应该是一个函数指针。怎么办?可以在prog1函数体内再包一层函数,把这个函数指针返回

def func1():
print("run func1")

def prog1(func):
def wrapfunc():
print("program start")
func()
return wrapfunc

func1 = prog1(func1)

func1()
函数prog1这样的结构就是一个装饰器,使用时只需要把被装饰的函数指针传func1传参给prog1,然后再赋值给func1,如此调用func1就会连装饰器一起调用

但是func1 = prog1(func1)这样的写法麻烦且不具有共通性,所以python提供了一种装饰器的标准用法

def prog1(func):
def wrapfunc():
print("program start")
func()
return wrapfunc

@prog1
def func1():
print("run func1")

func1()
prog1是装饰器函数,func1是被装饰的函数,只需要在定义被装饰的函数前面用@符号引出装饰器函数名称,就实现了把被装饰的函数指针传给调用的装饰器函数然后赋值给被装饰函数指针的功能

结束了吗?并没有!

如果你觉得最后调用的func1还是以前的func1就错了,不信可以打印一下它的名称:

print(func1.name)
打印结果:wrapfunc

为什么?因为func1 = prog1(func1)时,调用prog1(func1)返回的就是wrapfunc函数,然后又赋值给了func1,所以func1已经不是之前的func1了。它重写了函数的名字和注释文档

有解决的办法吗?有!!!

python提供了一个函数functools.wraps解决这个问题

from functools import wraps

def prog1(func):
@wraps(func)
def wrapfunc():
print("program start")
func()
return wrapfunc

@prog1
def func1():
print("run func1")

func1()
@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性

总结:

装饰器本质上是函数,需要编写
函数只有加上后面的括号才是调用,只有函数名,是函数指针
函数指针可以作为参数传参
函数指针作为对象可以赋值给其他的变量
函数体内可以定义其他的函数

目录
相关文章
|
8天前
|
监控 测试技术 Python
颠覆传统!Python闭包与装饰器的高级实战技巧,让你的项目效率翻倍
【7月更文挑战第7天】Python的闭包与装饰器是强大的工具。闭包是能记住外部作用域变量的内部函数,常用于动态函数创建和工厂模式。例如,`make_power`返回含外部变量`n`的`power`闭包。装饰器则允许在不修改函数代码的情况下添加新功能,如日志或性能监控。`my_decorator`函数接收一个函数并返回包装后的函数,添加了前后处理逻辑。掌握这两者,可提升编程效率和灵活性。
17 3
|
8天前
|
程序员 Python
从零到一,彻底掌握Python闭包与装饰器的精髓,成为编程界的隐藏Boss
【7月更文挑战第7天】探索Python编程的两大基石:闭包与装饰器。闭包是内部函数记住外部作用域的变量,如`make_multiplier_of`返回的`multiplier`,它保持对`n`的引用。装饰器则是函数工厂,接收函数并返回新函数,如`my_decorator`,它在不改变原函数代码的情况下添加日志功能。掌握这些,让代码更优雅,效率更高,助你成为编程高手。
16 3
|
8天前
|
程序员 Python
程序员必看!Python闭包与装饰器的高级应用,让你的代码更优雅、更强大
【7月更文挑战第7天】Python中的闭包和装饰器是高级特性,用于增强代码功能。闭包是内部函数记住外部作用域的变量,常用于动态函数和函数工厂。示例展示了`make_multiplier_of`返回记住n值的`multiplier`闭包。装饰器则是接收函数并返回新函数的函数,用于不修改原函数代码就添加功能。`my_decorator`装饰器通过`@`语法应用到`say_hello`函数上,展示了在调用前后添加额外行为的能力。这两种技术能提升代码的优雅性和效率。
16 3
|
8天前
|
Python
Python编程实战:利用闭包与装饰器优化日志记录功能
【7月更文挑战第7天】Python的闭包和装饰器简化了日志记录。通过定义如`log_decorator`的装饰器,可以在不修改原函数代码的情况下添加日志功能。当@log_decorator用于`add(x, y)`函数时,调用时自动记录日志。进一步,`timestamp_log_decorator`展示了如何创建特定功能的装饰器,如添加时间戳。这些技术减少了代码冗余,提高了代码的可维护性。
15 1
|
8天前
|
Python
Python黑魔法揭秘:闭包与装饰器的高级玩法,让你代码飞起来
【7月更文挑战第7天】Python的闭包和装饰器是提升代码效率的神器。闭包是能记住外部作用域变量的内部函数,常用于动态函数创建。示例中,`make_multiplier_of`返回一个保留`n`值的闭包。装饰器则是一个接收函数并返回新函数的函数,用于在不修改原函数情况下添加功能,如日志或性能追踪。`@my_decorator`装饰的`say_hello`函数在执行时会自动加上额外操作。掌握这两者,能让Python代码更优雅、强大。**
|
1天前
|
缓存 测试技术 Python
Python中的装饰器:优雅地增强函数功能
在Python编程中,装饰器是一种强大的工具,它能够在不改变函数本身的情况下,动态地增强其功能。本文将深入探讨装饰器的工作原理、常见用法以及如何利用装饰器提高代码的可重用性和可维护性。
|
3天前
|
UED Python
Python装饰器怎么做重试机制
**使用Python装饰器实现的重试机制**简化了对可能出现临时故障的函数的处理,增强系统稳定性和用户体验。文中提供了一个简单的装饰器示例,允许在达到最大重试次数前,按设定间隔自动重试失败的函数调用。这种机制在分布式系统、网络通信中尤为重要,可应对网络波动、资源紧张等问题,避免服务中断。通过添加`@retry`装饰器,无需大量修改代码即可为函数添加重试功能。
|
8天前
|
测试技术 Python
Python中的装饰器详解与应用
在Python编程中,装饰器是一种强大的工具,它可以优雅地修改函数或类的行为。本文将深入探讨装饰器的概念、语法结构及其在实际开发中的应用场景,帮助读者更好地理解和利用这一Python的高级特性。
|
8天前
|
监控 测试技术 Python
探索Python魅力:利用闭包与装饰器优化代码结构
【7月更文挑战第7天】Python中的闭包和装饰器是强大工具。闭包是能记住外部作用域变量的内部函数,常用于动态函数创建和数据封装。装饰器是接收函数并返回新函数的函数,用于在不修改原代码的情况下扩展功能,如日志或性能监控。通过示例展示了如何使用它们优化代码结构和提升效率。掌握这两者,能写出更优雅高效的Python代码。
|
9天前
|
Python
惊艳!原来Python闭包与装饰器可以这样玩,让你的代码瞬间高大上
【7月更文挑战第6天】Python中的闭包和装饰器是代码复用和增强功能的利器。闭包是能记住外部作用域变量的内嵌函数,常用于封装和优化代码。例如,`make_multiplier_of`生成了乘法函数,如`times3`和`times5`,避免了重复代码。装饰器则不修改原函数即可添加新功能,如`my_decorator`在函数调用前后打印信息。当两者结合,如`repeat`装饰器,可以根据参数动态改变函数行为,如重复执行`greet`函数。闭包和装饰器的协同使用提升了代码的优雅性、效率和可扩展性。
15 0