Python高阶函数装饰器

news2025/1/11 5:10:10

“ 从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接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性

总结:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/114337.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言—宏定义

宏定义的作用是替换&#xff0c;再复杂也只能替换&#xff0c;不能用做计算&#xff1b; 一个源文件将另一个源文件的全部内容包含进来&#xff1b; 条件编译&#xff1b; 不带参数的宏定义&#xff1a; #include <stdio.h> #define PI 3.14int main() {printf("…

聊聊Redis消息队列-实现异步秒杀

一、前言 消息队列&#xff08;Message Queue&#xff09;, 字面意思就是存放消息的队列&#xff0c;最简单的消息队列模型包括3个角色&#xff1a; 消息队列&#xff1a;存储和管理消息&#xff0c;也被称为消息代理&#xff08;Message Broker&#xff09;;生产者&#xff…

Shell编程补充

Shell编程补充shell的变量定义变量的单双引号的不同输出变量父子shellshell子串BASHshell子串的用法shell统计变量长度输出程序运行时间结论:shell扩展变量用于处理变量值的创建子shell(进程列表)查看是否开启子shell在运行内置命令,外置命令shell编程总结shell的变量 定义变量…

小黑实习debug中遇到了函数式编程的混乱,特此进行的日常积累:python函数积累1

函数参数中有默认值&#xff0c;在函数内部会创建一块区域并维护这个默认值 # 在函数内存中会维护一块区域存储 [1,2,666,666,666] 100010001 def func(a1,a2[]):a2.append(666)print(a1,a2)func(100) func(1000)100 [666] 1000 [666, 666] def func(a1,a2[]):a2.append(666…

【nowcoder】笔试强训Day7

目录 一、选择题 二、编程题 2.1Fibonacci数列 2.2合法括号序列判断 一、选择题 1.JAVA属于&#xff08; &#xff09;。 A 操作系统 B 办公软件 C 数据库系统 D 计算机语言 计算机软件主要分为系统软件与应用软件两大类。系统软件主要包括操作系统、语言处理系统、数…

three.js之形状缓冲几何体

文章目录简介例子解释其他圆弧矩形专栏目录请点击 简介 Shape用来定义一个二维形状平面 官网常常与ShapeGeometry(形状缓冲几何体)搭配使用 官网&#xff0c;我们可以下运行下面的例子 例子 <!DOCTYPE html> <html lang"en"><head><meta cha…

玩转GPT--在线文本生成项目[可入坑~科普系列]

文章目录前言效果页面说明文字个数top_KTop_Ptemperature聊天上下文关联记忆项目部署获取项目获取模型运行彩蛋总结前言 没办法&#xff0c;最近ChatGPT杀疯了&#xff0c;没忍住&#xff0c;还是想look&#xff0c;look。没办法&#xff0c;哪个帅小伙能够忍受的了一个可以和…

数学知识---数论(质数和约数)

文章目录 1.质数1.1质数的判定---试除法1.2分解质因数---试除法1.3筛质数2.约数2.1试除法求约数2.2约数个数2.3约数之和2.4最大公约数---欧几里得算法(辗转相除法)1.质数 质数是针对所有大于1的自然数定义的,在大于1的整数中,如果只包含1和本身这两个约数,就被定义成为质…

【SpringCloud Alibaba】 初始化Sentinel

Sentinel 概念 特征 主要特征 开源生态​ 开启控制台 初始化工程 Sentinel 概念 分布式系统的流量防卫兵。随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点&#xff0c;从流量控制、流量路由、熔断降级、系统自适应过载保护…

Biotin-PEG-NH2,Biotin-PEG-amine,生物素-PEG-氨基材料改性用化学试剂

英文名称&#xff1a;Biotin-PEG-NH2&#xff0c;Biotin-PEG-amine 中文名称&#xff1a;生物素-聚乙二醇-氨基 Biotin-PEG-NH2是氨基化PEG中的一种&#xff0c;他可以用于材料改性&#xff1b;氨基和很多基团可以反应&#xff0c;如&#xff1a;羧基&#xff0c;活性酯&…

JavaScript:封装单向链表10种常见的操作方法

链表的优势 1.要存储多个元素的时候&#xff0c;除了数组还可以选择链表。 2.与之数组不同的是&#xff0c;链表中的元素在内存中不必是连续的空间。 3.链表中的每个元素由一个存储元素本身的节点和一个指向下一个节点的引用(指针或者连接)组成。 相比于数组&#xff0c;链表有…

QGIS基础:根据字段属性值或基于规则进行分类符号化显示

以下操作是对数据进行分类符号化&#xff0c;下面是原始操作数据&#xff1a; 基于分类符号化的字段是如下所示&#xff08;ZDTZM&#xff09;: A B C D 找到数据图层&#xff0c;右键属性&#xff0c;找到【符号化】&#xff0c;点击如下所示的分类&#xff1a; 在【valu…

mysql数据库完整实例-“汽车维修”

mysql数据库创建&#xff0c;编写&#xff0c;查询&#xff0c;自定义函数实战案例 创建汽车修理数据库&#xff0c;并完成数据库编写&#xff1a; 本文分三个部分&#xff0c;第一部分为数据库的创建编写和基础查询&#xff0c;第二部分为关联查询等复杂查询方法&#xff0c…

实验四:完整性实验

【实验目的】 掌握实体完整性、参照完整性和用户自定义完整性的定义的维护方法 【实验内容】 要实现这样一个功能&#xff1a;医生根据药品价表选择处方药品&#xff0c;录入数量和使用天数&#xff0c;系统根据医生选择的药品和录入的信息自动生成处方主表和处方明细表。功能…

Flink-按键分区状态-算子状态-广播状态

文章目录1. 按键分区状态&#xff08;Keyed State&#xff09;1.2基本概念和特点1.3 支持的结构类型1.4 代码实现1.5 状态生存时间&#xff08;TTL&#xff09;2 算子状态&#xff08;Operator State&#xff09;2.1 基本概念和特点2.2 状态类型2.3 代码实现3. 广播状态&#x…

2022年安徽建筑施工塔式起重机(建筑特种作业)模拟题库及答案

百分百题库提供特种工&#xff08;塔式起重机&#xff09;考试试题、特种工&#xff08;塔式起重机&#xff09;考试真题、特种工&#xff08;塔式起重机&#xff09;证考试题库等,提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 87.塔式起重机滑轮上…

基于历史对比学习的时序知识图谱推理

时序知识图谱 知识图谱&#xff08;KGs&#xff09;作为人类知识的集合&#xff0c;在自然语言处理、推荐系统和信息检索等领域显示展现了很好的前景。传统的KG通常是一个静态知识库&#xff0c;它使用图结构数据拓扑&#xff0c;并以三元组&#xff08;s, p, o&#xff09;的…

自定义ContentProvider案例

自定义ContentProvider案例 1.条件准备 app5往外暴漏数据app7接收和操作远程数据图1 app5目录结构 图2 app7目录结构 2.参考代码 完整代码&#xff1a; https://download.csdn.net/download/weixin_41957626/87346497 1)app5的代码 &#xff08;1&#xff09;app5的entity&…

C#项目实战——【实例】企业人事管理系统(一):1、系统分析;2、系统设计;3、系统运行环境;

学习《C#从入门到精通》&#xff0c;边学边练记录实现过程。 1、系统分析 1.1、需求分析 基于其他企业人事管理软件的不足&#xff0c;要求能够制作一个可以方便、快捷地对职工信息进行添加、修改、删除的操作&#xff0c;并且可以在数据库中存储相应职工的照片。为了能够更…

Magic Live智慧引擎发力,荣耀吹响智慧服务变革号角

人类的不断进步&#xff0c;核心源自对生活的“不满足”。 就在十几年前&#xff0c;诺基亚、黑莓等手机还被当做走在时代前沿的产品&#xff0c;触屏笔等设计风靡一时。但后来人们发现&#xff0c;触屏笔非常不方便&#xff0c;于是迅速被淘汰&#xff0c;更为先进的触摸屏诞…