装饰器---python

一、柯里化

概念:将原来接受两个参数的函数变成新的接受一个参数的函数过程,新的函数返回一个以原有第二个参数为参数的函数

例如:

例一

原函数是add(x,y),柯里化的目标是add(x)(y),如何实现呢?

相当于嵌套函数,有闭包,内层函数inner调用量外层函数变量x,形成了闭包。

再来看:

例二

柯里化的目标是

1   def(x)(y,z)

2     add(x,y)(z) 

 

3   add(x)(y)(z)

了解了柯里化以后,下面就开始进入装饰器的讲解

二、无参装饰器

装饰器:用来装饰函数或类

由来需求为加法函数增加记录实参的功能

可以写成这样:

但是存在一个问题,add是业务功能代码,增加记录实参功能的代码属于非业务功能代码,不好,

也就是侵入式代码,剥离不易,假设换一种思维,A函数需要记录,B函数也需要记录,记录功能也不属于A和B的业务功能,而且它不是A和B的业务功能,而且它是A和B的公用功能,如果有c函数也需要此功能怎么办?

这里可以创建一个函数:logger来实现这个功能

改变传参的方式,关键字传参和位置传参

函数的每次调用都是相互独立的,互不干扰,别看add的内存地址一样,就认为他是覆盖调用。

下面调整一下代码:

理解了这个以后装饰器对你来说就不是个问题

装饰器语法很简单:

@标识符
标识符指向的是一个函数用一个函数来装饰他下面的函数logger函数称为装饰器add被称为被装饰器或被包装函数
logger习惯上称为wrapper
add习惯上称为wrapperd
本质上 无参装饰器logger实际上等效为一个参数的函数
无参装饰器logger
@logger会把他下面紧挨着的函数标识符提上来作为他的实参xyz=logger(xyz)
def xyz():
    pass

三、日志记录装饰器实现

四、文档字符串

在函数(类和模块)语句块的第一行,且习惯是多行的文本,所以多使用三引号

文档字符串也是一条合法语句,惯例是首字符大写,第一行写概述,空一行,第三行写详细概述

可以使用特殊属性__doc__访问这个文档

如:

五、装饰器文档问题

结果:

被装饰后,你会发现add的函数名和文档都变了?如何解决呢?

函数也是对象,特殊属性也是属性,也可以被覆盖,现在访问访问的add实际上是wrapper函数,所以使用原来定义的add函数和doc文档属性覆盖wrapper对应的属性就可以了

这叫用到带参装饰器了

六、带参装饰器

能否把copy_properties改成装饰器呢?这个装饰器就是带参装饰器

结果:

像copy_properties(fn)这种装饰器后面跟着一个函数的装饰器称为带参装饰器

先执行add=logger(add),在函数logger内部遇到copy_properties装饰器,

执行copy_properties(fn)(wrapper)这里的fn就是原函数add

也就是执行copy_properties(add)(wrapper)

下一步执行_copy函数

wrapper.__name__=add.__name__

wrapper.__doc__=add.__doc__

_copy返回None,因为修改add的名称和属性,所以_copy返回dst

替换完成以后,就继续执行logger内部函数wrapper

进行函数的打印和函数的调用传参,@logger装饰器语句执行完后,打印add的名称和doc

那么能不能给logger设置一个阀值,执行时长超过阀值记录一下?

运行结果

七、annotation注解

由于python是动态语言,太灵活,越灵活越难掌握

不到运行时,无法判断类型是否正确;

难发现:由于不做检查,往往到运行时问题才显现出来,或到了线上运行才暴露出来

难使用:函数使用者看到函数时,并不知道设计者的意图,如果没有详尽的文档,使用者只能猜测数据类型。也不知道返回类型是什么。

如何解决这个问题呢?

解决方法一:函数注解:

声明函数类型,这是非强制性约束

结果

也会出现函数传参的错误:如

可以在函数内部写isinstance来判断参数类型是否正确,但是检查可以看做不是业务代码,写在里面就是侵入式代码。如

可以用装饰器来 解决首先先来了解一下inspect模块

七.1、inspect模块

  • inspect模块是 Python 标准库中的一个强大工具,主要用于获取有关活动对象(如模块、类、方法、函数等)的信息。它提供了许多函数来检查对象的源代码、签名、模块路径等诸多细节。
  • signature函数
  • 用于获取可调用对象(如函数、方法)的参数签名信息。它返回一个Signature对象,其中包含了参数的名称、默认值、是否可变等信息。
  • 首先,inspect.signature获取了add的签名信息,打印sig会显示函数签名的整体情况,如(arg1, arg2 = 2)。而sig.parameters则是一个有序字典,包含了参数的详细信息,如参数名称、默认值等。可以通过遍历这个字典来获取每个参数的具体细节。

解决函数传参类型错误的问题

使用装饰器

下面了解一下各个形参之间的属性

八、functools模块

8.1、reduce

functools.reduce(function,iterable[,initial])

就是减少的意思,如果初始值没有提供,就在可迭代对象中取一个

从上面可以看出reduce是迭代计算的,所以要让reduce实现sum去和功能,可以这样改

8.2、partial偏函数

把函数参数部分固定下来,相当于为部分参数添加固定默认值,想成一个新函数,并返回这个新函数。这个新函数是对原函数的封装。

例1

为什么newfunc(7,8)这种函数传参方式是错误的呢?很简单按位置传参的话就是newfunc(x=7,y=8,y=5)。形参y重复定义

如果你不知道如何传参,可以用函数签名来查看

再来看一种

例2

第二种固定

有标签可知,x和y是关键字传参,*是位置传参

newfunc(1,2)#重复定义 newfunc(y=1,x=2,*args,y=20,x=10)

如果你实现不了解partial如何传参,可以了解函数是如何实现的

这里参考的是python document

8.3 、lru-cache(最少使用,cache缓存)带参装饰器

functools.lru_cache(maxsize=128,typed=False)

  • maxsize:这是lru_cache最重要的参数,用于指定缓存的最大大小。
    • 如果maxsize设置为None,缓存可以无限制地增长。这在某些情况下可能会导致内存占用过多,但对于一些计算成本非常高且输入参数组合有限的函数来说是很有用的。
    • 如果maxsize是一个整数,例如maxsize = 128,那么缓存最多存储 128 个函数调用的结果。当缓存已满,需要存储新的结果时,会根据 LRU 策略清除最久未被使用的缓存项。
  • typed:这是一个可选的布尔值参数。
    • 如果typed=Truelru_cache会分别缓存不同类型参数的结果。例如,fibonacci(1)fibonacci(1.0)会被视为不同的调用,分别缓存它们的结果。
    • 如果typed=False(默认值),不会区分参数的类型

应用斐波那契数列

当调用fib函数时,例如fib(5)lru_cache会首先检查缓存中是否已经存在fib(5)的结果。如果存在,就直接返回缓存中的结果;如果不存在,就计算。也就是缓存命中,用空间换时间。

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

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

相关文章

Spring AI 框架使用的核心概念

一、模型(Model) AI 模型是旨在处理和生成信息的算法,通常模仿人类的认知功能。通过从大型数据集中学习模式和见解,这些模型可以做出预测、文本、图像或其他输出,从而增强各个行业的各种应用。 AI 模型有很多种&…

知识见闻 - 数学: 均方根 Root Mean Square

What is Root Mean Square (RMS)? 在统计学上,均方根(RMS)是均方的平方根,而均方是一组数值的平方的算术平均数。均方根也称为二次均值,是指数为 2 的广义均值的一种特例。均方根也被定义为基于一个周期内瞬时值的平方…

基于Spring AI alibaba组件AI问答功能开发示例

基于Spring AI alibaba组件AI问答功能开发示例 功能效果图: http://localhost:9999/ai/test http://localhost:9999/ai/chat?inputai 配置 application.yaml 指定 API-KEY(可通过访问阿里云百炼模型服务平台获取,有免费额度可用。&#x…

Linux - 线程基础

文章目录 1.什么是线程2.线程vs进程3.线程调度4.线程控制4.1 POSIX线程库4.2创建线程4.3线程终止4.4线程等待4.5线程分离 5、线程封装 1.什么是线程 在Linux操作系统中,线程是进程内部的一个执行流。在Linux操作系统下,执行流统称为轻量级进程&#xff0…

5、AI测试辅助-生成测试用例思维导图

AI测试辅助-生成测试用例思维导图 创建测试用例两种方式1、Plantuml思维导图版本 (不推荐)2、Markdown思维导图版本(推荐) 创建测试用例两种方式 完整的测试用例通常需要包含以下的元素: 1、测试模块 2、测试标题 3、前置条件 4、…

学习日志014--用python实现顺序表

之前我们用c语言实现顺序表,今天就然我们用python来复习一遍 一、创建顺序表 python的类可以代替c中的结构体作为复合数据类型。 创建学生类,并用装饰器将方法属性化,便于之后的修改。属性装饰器,可以在保护私有属性&#xff0…

PTA编程题:N个数求和

问题描述 思路分析 问题分解 输入处理:将分数拆解为分子和分母,存储并处理。 分数相加规则: 即分子相加、分母相乘。 结果化简:求分数的最大公因数(GCD),将其约分至最简形式。 带分数处理&…

Selenium + 数据驱动测试:从入门到实战!

引言 在软件测试中,测试数据的多样性和灵活性对测试覆盖率至关重要。而数据驱动测试(Data-Driven Testing)通过将测试逻辑与数据分离,极大地提高了测试用例的可维护性和可扩展性。本文将结合Selenium这一流行的测试工具&#xff0…

RK3568平台(中断篇)ARM中断流程

一.ARM 处理器程序运行的过程 ARM芯片属于精简指令集计算机 (RISC: Reduced Instruction Set Computing),它所用的指令比较简单,有如下特点: ① 对内存只有读、写指令 ② 对于数据的运算是在CPU内部实现 ③ 使用RISC指令的CPU复杂度小一点,易于设计 比如对于 a=a+b 这…

视频修复技术和实时在线处理

什么是视频修复? 视频修复技术的目标是填补视频中的缺失部分,使视频内容连贯合理。这项技术在对象移除、视频修复和视频补全等领域有着广泛的应用。传统方法通常需要处理整个视频,导致处理速度慢,难以满足实时处理的需求。 技术发…

推荐一款专业电脑护眼工具:CareUEyes Pro

CareUEyes Pro是一款非常好用的专业电脑护眼工具,软件小巧,界面简单,它可以自动过滤电脑屏幕的蓝光,让屏幕显示更加的不伤眼,更加舒适,有效保护你的眼睛,可以自定义调节屏幕的色调,从…

04 - 镜像存储机制

04 - 镜像存储机制 1. OverlayFS 存储原理 OverlayFS 结构分为三个层: LowerDir、Upperdir、MergedDir LowerDir (只读层) 只读的 image layer,其实就是 rootfs, 在使用 Dockfile 构建镜像的时候, Image Layer 可以分很多层,所以…

Element UI 组件库详解【Vue】

文章目录 一、引言二、安装并使用1. 安装2. 使用 三、常见组件说明1. 基础组件2. 布局组件3. 布局容器4. 选择框组件5. 输入框组件6. 下拉框组件7. 日期选择器8. 上传组件9. 表单组件10. 警告组件11. 提示组件12. 表格组件 一、引言 官方网站,element.eleme.cn El…

通过socket设置版本更新提示

1.项目使用的是git所以使用git仓库的短哈希作为版本更新标识,将该字符写入public文件,此处需要注意后端访问静态资源的路径。 在vue.config.js文件中写入 function excuteVersion() {const fs require(fs)const { execSync } require(child_process)…

相机触发模式

参考自:相机触发模式_硬触发和软触发的区别-CSDN博客 一、图像采集模式分类 相机的图像采集模式分为内触发模式与外触发模式。其中内触发模式包含连续采集、单帧采集两种形式;外触发模式包含软件外触发、硬件外触发。本文以海康相机的软件平台作介绍&a…

脚手架vue-cli,webpack模板

先安装node.js,它是服务器端,用于给页面提供服务。前端学习不需要会node.js,只需要学会node.js衍生出来的npm命令即可。 npm 是node.js的一个工具,作用是进行包管理,npm是node.js的包管理器。 接着安装脚手架&#xff…

Stable Diffusion核心网络结构——CLIP Text Encoder

🌺系列文章推荐🌺 扩散模型系列文章正在持续的更新,更新节奏如下,先更新SD模型讲解,再更新相关的微调方法文章,敬请期待!!!(本文及其之前的文章均已更新&…

ggplot2 分面图等添加注释文字,相加哪里加哪里: 自定义函数 AddText()

如果分面图上还想再添加文字,只能使用底层的grid包了。 函数定义 # Add text to ggplot2 figures # # param label text you want to put on figure # param x position x, left is 0, right 1 # param y position y, bottom is 0, up 1 # param color text color…

ubuntu中使用ffmpeg和nginx推流rtmp视频

最近在测试ffmpeg推流rtmp视频,单独安装ffmpeg是无法完成推流的,需要一个流媒体服务器,常用nginx,可以直接在ubuntu虚拟机里面测试一下。 测试过程不涉及编译ffmpeg和nginx,仅使用基本功能: 1 安装ffmpeg …

解决upload上传之后,再上传没有效果

解决upload上传之后,再上传没有效果 注释:这是第二次上传,两次网络请求都是第一次上传的,这次上传没有网络请求 原因:在我的代码里我限制了上传数量为1,然后上传成功后,上传列表没有清空&#…