python中神奇的装饰器

需求:实现一个可以统计代码的运行时间-CSDN博客

装饰器就是我们常见的在类或函数上的@装饰器,比如unittest里@ddt,它可是一种好用的工具。如果你同事写了一坨代码,你想给这一坨代码扩展新的功能,这个时候就用到了装饰器,它的神奇在于,它既不改变原功能函数的内部代码,还不改变调用方法的情况下,就给你同事的这坨代码扩展了新的功能。该说不说,设计装饰器的大佬真是给我们带来了极大的方便。

装饰器原理:

@装饰器  等同于调用装饰器,就是把被装饰的函数,当成参数传入装饰器中,保存在封闭作用域中。

书接上回,上篇就是用装饰器实现了统计代码运行时间的功能, 上篇的函数装饰器,都是用闭包的形式;什么又是闭包呢?

闭包:简单的说就是 一个函数在一个封闭作用域内

形式:

一个函数嵌套一个函数;

外层函数return返回内层函数;

这样内层函数就保证在外层函数这个封闭作用域内了

在内层函数里:

扩展的代码1

被装饰的函数

扩展的代码2

这就给被装饰的函数扩展新功能啦。

def decorator(func):def wrapper():print("扩展的代码1")func()print("扩展的代码2")return wrapper@decorator  # work = decorator(work)
def work():print("----------写代码-----------")work()

这样一个基本的装饰器就完成啦。

这个时候,我们装饰的函数有参数,要怎么做呢?

def decorator(func):def wrapper(*args, **kwargs):print("-----------开机,打开软件--------------")res = func(*args, **kwargs)print("------------关机,底薪到手--------------")return resreturn wrapper@decorator  # work = decorator(work)
def work(a, b):print("----------写代码-----------")return a + bwork(10, 30)

再复杂一点,我们装饰器本身带有参数呢? 

@decorator(5)  =====》等同于 被装饰的函数 = decorator(5)(被装饰的函数)

def decorator(n):"""最外层的参数n,接收装饰器传进来的值"""def wrapper(func):"""第二层参数func,接收被装饰的函数"""def wrapper1(*args, **kwargs):"""第三次参数,接收被装饰的函数调用时传进来的参数"""print(n)print("装饰器扩展的功能代码1")res = func(*args, **kwargs)print("装饰器扩展的功能代码2")return resreturn wrapper1return wrapper@decorator(5)  # work = decorator(5)(work)
def work():print("人生苦短,我学python")work()

 至此,通过函数实现装饰器,就这些了。(提一句,装饰器有个副作用,问题也不大,在这儿就不介绍了。)

你就想啦,通过函数能实现装饰器,那能不能通过类实现装饰器呢?你是会举一反三的,当然可以啦。这个时候,你又学了一个魔术方法__call__,这个时候你就能通过类实现装饰器啦。

这个魔术方法有什么作用呢?类创建出来对象能不能调用,就取决于这个类中有没有魔术方法__call__。

import timeclass CountTime:def __init__(self, func):# func:是被装饰的函数,传入进来之后保存为func属性self.func = funcdef __call__(self, *args, **kwargs):st = time.time()# 调用原功能函数res = self.func(*args, **kwargs)et = time.time()print("函数执行的时间为:", et - st)return res@CountTime  # ===> work = CountTime(work)  实例化对象
def work():time.sleep(2)work()

装饰器好神奇,怎么用好这个工具,还得看个人;用函数或者类实现装饰器,我这里都是装饰的函数,一样的,也可以去装饰器类,试着去写一下吧。

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

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

相关文章

图像处理神经网络数据预处理步骤的详细解释和分析

1. 尺寸调整(Resizing) 目的:神经网络通常需要固定尺寸的输入图像。通过统一图像尺寸,可以确保输入的一致性,使得网络能够正常处理。 方法:将所有输入图像调整为特定的尺寸(例如224x224像素&a…

C++STL---string知识汇总

前言 我们现在开始CSTL的学习,从这时开始我们就要锻炼自己查看英文文档的能力,每种数据结构都有上百个接口函数,我们把他们全部记下来是不可能的,所以我们只记最常见的20几个接口,其他的大概熟悉有什么功能&#xff0…

深入JVM元空间以及弹性伸缩机制

个人博客 深入JVM元空间以及弹性伸缩机制 | iwts’s blog JVM内存模型中元空间所在位置 即在JVM运行时的内存模型。总体上有这样的图: 元空间 上面的图其实有点不太准。方法区本质上只是JVM的一个标准,不同JVM在不同版本下都可能有不同的实现&#x…

Matlab中函数或变量 ‘eeglab‘ 无法识别

EEGLAB 没有安装或添加到 MATLAB 路径中: 确保已经安装了 EEGLAB,并且将其添加到 MATLAB 的路径中。您可以通过在 MATLAB 命令窗口中运行 which eeglab 来检查是否能够找到 EEGLAB。 EEGLAB 函数路径设置错误: 如果已经安装了 EEGLAB&#x…

可以免费试用得微信辅助工具wetool升级版,可以群发,可以清理僵尸粉,可以自动回复,可以批量添加

今天给大家推荐一款我们目前在使用的电脑群发工具掘金小蜜,不仅可以无限多开,方便你同时管理多个账号,群发功能更是十分强大,轻松释放你的双手。 掘金小蜜(只支持Win7及以上操作系统,没有推Mac版和手机客户…

【知识拓展】LocalTunnel-高性价比的内网穿透工具(2)

前言 上一篇通过ngrok进行内网穿透,有几个问题: ①需要注册,而且注册需要科学上网,相对麻烦 ②安装配置相对麻烦,authtoekn有限制 上述相对,指的是在非生产环境中做一个简单内网穿透,相对于…

neo4j开放远程连接

注:本博客所用neo4j版本为社区5.12版 第一步:修改neo4j配置文件 首先找到neo4j的安装位置,点击进入conf文件夹,随后点击neo4j.conf文件,在“Network connector configuration”下面的单元中找到server.default_liste…

汽车IVI中控开发入门及进阶(二十):显示技术之LCDC

TFT LCD=Thin Film Transistor Liquid Crystal Display LCDC=LCD Controller 薄膜晶体管液晶显示器(TFT LCD)控制器在驱动现代显示技术的功能和性能方面起着关键作用。它们充当屏幕后面的大脑,仔细处理数字信号,并将其转化为精确的命令,决定每个像素的行为,决定它们的…

计算机网络基本概念

文章目录 情景带入一些基本概念网络网络编程:7层网络模型OSI:TCP/IP Protocol Architecture Layers与OSI的对应关系SocketClient-Server Application报文段:传输协议:Mac地址IP地址端口URL 情景带入 随着时代的发展,我…

【机器学习300问】92、训练集和测试集来自不同分布,如何构建模型?

假设有一个团队想开发手机应用识别识别小猫图片。但由于深度学习算法对训练数据的要求很高。这个团队为了让训练集更大,会收集来自不同分布的数据进行训练。业余用户上传图片与专业高清图片有差异,这种做法虽然能获得大量的训练数据,但训练数…

SQL Server--死锁

今天,客户反应打不开xxx页面了。好家伙肯定锁表了。。。。。 只能先吧死锁进程先kill掉,不能耽误客户生产环境运行。。。。。 一定要看看是那张表发生了死锁 1、查询死锁语句 select dbid,* from sys.sysprocesses where 11 and spid >50 and blo…

STM32—HAL-PWM-舵机180(每个频率对应每个角度)

1开启时钟 2开启定时器和通道设置为PWM模式 3将定时时间设置为50Hz(20ms)//每25为1ms 4代码编写 4.1开启PWM 4.2改PWM的占空比 4.3效果0~180度在0度 源码 /* USER CODE BEGIN Header */ /******************************************************************************…

嵌入式开发----协议组成以及设计

1 引言 随着信息技术的快速发展,人们之间的通信和数据交换变得越来越频繁和复杂。而在这个过程中,协议起着至关重要的作用。协议是一种规范或约定,用于规定通信双方之间的数据交换格式、传输方式、通信规则等,从而确保通信的顺利…

《C++ Primer Plus》第十一章复习题和编程练习

这里写目录标题 一、复习题二、编程练习 一、复习题 1. 使用成员函数为Stonewt类重载乘法运算符,该运算符将数据成员与double类型的值相乘。注意,当用英石和磅表示时,需要进位。也就是说,将10英石8磅乘以2等于21英石2磅。 答&am…

Imperva 导致的ORAbase 乱码

DBCA Failing Because Of Garbage Characters In ORACLE_BASE Variable (Doc ID 2947963.1)​编辑To Bottom In this Document Symptoms Changes Cause Solution APPLIES TO: Oracle Database Configuration Assistant - Version 19.14.0.0.0 and later Oracle Database - E…

本地镜像文件怎么导入docker desktop

docker tag d1134b7b2d5a new_repo:new_tag

PageHelper分页

文章目录 PageHelper分页ThreadLocalMap和ThreadLocal执行完PageHelper.startPage之后,分页参数存储到哪里了?Page和List的关系?PageInterceptor分页拦截器的作用?PageInfo的作用与结构?最后看下引入的pagehelper分页依…

字节跳动 (提前批-算法工程师-电商业务) 一面面经

文章目录 面试情况1、对简历项目提问:1.1、介绍项目中的xx分类、xx概念分类、xx概念归一化,具体做法,为什么这么做?1.2、标注问题,如何标注?1.3、如何设计prompt让chatgpt得到高质量标注?1.4、类…

perl:用 Net::Server 创建简单的流媒体服务器来播放.flv文件

这是一个使用Perl Net::Server 模块创建的简单流媒体服务器示例,它能够播放.flv文件。 首先,确保安装了Net::Server模块,如果没有安装,可以使用CPAN来安装它: 运行 cpan Net::Server RHANDOM/Net-Server-2.014.tar.…

Spring框架常见注解(Spring,SpringMvc,SpringBoot)

Spring常见注解 Component、Controller、Service、Repository 使用在类上用于实例化Bean Autowired 使用在字段上用于根据类型依赖注入 Qualifier 结合Autowired一起使用用于根据名称进行依赖注入 Scope 标注Bean的作用范围 Configuration 指定当前类是一个 Spring 配…