Python装饰器的具体实用示例
示例1:普通装饰器
def name(n):def func(x):res = n(x+x)return resreturn func@name
def run(x): # run = name(run)print(x)if __name__ == '__main__':run(1)
# 2
def name(n):def func(*x):res = n(x+x)return resreturn func@name
def run(x): # run = name(run)print(x)if __name__ == '__main__':run(1)
# (1, 1)
上述二者的比较,注意传参参数。一个是普通的传值,一个是两个元组相加。
示例2:普通装饰器传值
def name(n):def func(x, y):res = n(x,y)return resreturn func@name
def run(x, y): # run = name(run)print(x, y)if __name__ == '__main__':run(1, 2)
# 1 2
试想,如何才能实现1+2,run函数中还是name函数中
def name(n):def func(x, y):res = n(x,y)return resreturn func@name
def run(x, y): # run = name(run)print(x + y)if __name__ == '__main__':run(1, 2)
在run函数中实现,name函数作用近似于调用的操作,也可以在name函数中实现
def name(n):def func(x, y):res = n(x,y)print(x + y)return resreturn func@name
def run(x, y): # run = name(run)# print(x + y)passif __name__ == '__main__':run(1, 2)
示例3-进阶:日志
import loggingdef name(n):def func(x, y):res = n(x,y)logging.basicConfig(format='%(asctime)s %(name)s %(levelno)s %(filename)s ''%(lineno)d %(message)s', level=logging.DEBUG)logging.info("执行了{},{},结果是{}".format(x,y,res))return resreturn func@name
def run(x, y): # run = name(run)return x+yif __name__ == '__main__':run(1, 2)
# 2023-03-01 12:24:10,474 root 20 ceshi_test.py 10 执行了1,2,结果是3
这里的结果貌似没有指明函数,影响不大,可以看看logging模块,也可以自己加。
import loggingdef name(n):def func(x, y):res = n(x,y)logging.basicConfig(format='%(asctime)s %(name)s %(levelno)s %(filename)s ''%(lineno)d %(funcName)s %(message)s', level=logging.DEBUG)logging.info("执行了{},{},{},结果是{}".format(n.__name__,x,y,res))return resreturn func@name
def run(x, y): # run = name(run)return x+yif __name__ == '__main__':run(1, 2)
# 2023-03-01 12:35:15,283 root 20 ceshi_test.py 9 func 执行了run,1,2,结果是3
可以看到,获取的运行函数其实不太一样。要想准确的获取,建议手写
示例4-进阶:时间计时器
import time
def timer(clock):def func(*args,**kwargs):start = time.time()res = clock(*args,**kwargs)print("耗时 {} S".format(time.time() - start))return resreturn func@timer
def run(x, y): time.sleep(1)print(x + y)if __name__ == '__main__':run(1, 2)
# 3
# 耗时 1.0103626251220703 S
上述是在不做任何操作的情况下,单纯用来计算程序运行时间。
示例5-再进阶-带参
def outwapper(out):def country(cont):def inwapper(*args,**kwargs):if out == '中国':print("你好啊,兄弟")else:print("你是哪个国家的")cont(*args,**kwargs)return inwapperreturn country@outwapper("中国")
def people():passif __name__ == '__main__':people()
是不是看起来麻烦了很多,仔细一看其实也久那么回事。传个参数,该返回的值还是得返回。
def outwapper(out):def country(cont):def inwapper(*args,**kwargs):if out == '中国':print("你好啊,兄弟")else:print("你是哪个国家的")cont(*args,**kwargs)return inwapperreturn country@outwapper("中国")
@outwapper("俄罗斯")
def people():passif __name__ == '__main__':people()
# 你好啊,兄弟
# 你是哪个国家的
可以多个装饰器作用同一个函数上,也能重复使用。
示例6-高阶-类装饰器
class Time(object):def __init__(self, func):self.func = funcdef __call__(self, *args, **kwargs):print(args,kwargs)@Time
def name():passif __name__ == '__main__':name()
套用格式即可,__init__中的参数是必须的,因为需要传递函数。
class Time(object):def __init__(self, func):self.func = funcdef __call__(self, *args, **kwargs):print(args,kwargs)@Time
def name(x,y):passif __name__ == '__main__':name('清安',age=18)
# ('清安',) {'age': 18}
很明显了吧,__call__中用来接收值并处理的。
传参
class Time(object):def __init__(self, func):self.func = funcdef __call__(self, evt):def wapper(*args, **kwargs):print(self.func, args, kwargs)return wapper@Time("中国")
def name(x, y):passif __name__ == '__main__':name('清安', age=18)
# 中国 ('清安',) {'age': 18}
evt是啥?
class Time(object):def __init__(self, func):self.func = funcdef __call__(self, evt):def wapper(*args, **kwargs):print(evt.__name__, args, kwargs)return wapper@Time("中国")
def name(x, y):print(x,y)if __name__ == '__main__':name('清安', age=18)
# name ('清安',) {'age': 18}
就是name函数的函数地址,如何使用evt参数呢?
class Time(object):def __init__(self, func):self.func = funcdef __call__(self, evt):def wapper(*args, **kwargs):evt(args,kwargs)# print(evt.__name__, args, kwargs)return wapper@Time("中国")
def name(x, y):print(x,y)if __name__ == '__main__':name('清安', age=18)
就是这么简单。
示例7-高阶-装饰类的装饰器
def func(cls):def inwapper(*args,**kwargs):print(cls.__name__)print(args)return inwapper@func
class User:def __init__(self,name):self.name = nameif __name__ == '__main__':User("清an")
# User
# ('清an',)
类中函数使用装饰器
def func(cls):def inwapper(x, *args, **kwargs):logging.basicConfig(format='%(asctime)s %(name)s %(levelno)s %(filename)s ''%(lineno)d %(funcName)s %(message)s', level=logging.DEBUG)logging.info("执行了{},结果是{},{},{}".format(cls.__name__,x, args, kwargs))return inwapper# @func
class User:@funcdef name(self, name, name1, age):# return name, name1, agepass
if __name__ == '__main__':u = User()u.name("清安","ANAN",age=18)
2023-03-01 18:36:36,310 root 20 ceshi_test.py 74 inwapper 执行了name,结果是<__main__.User object at 0x0000020A11DABE50>,('清安', 'ANAN'),{'age': 18}
为什么要有个x,因为self会被当作参数传递,直接把内存地址一起传走了,要么下标取值要么再来个参数接收这个self。要么类中不使用self
❝既然使用了self,那么装饰器中能用来调用属性吗,答案是当然可以。
❞
def func(cls):def inwapper(x, *args, **kwargs):logging.basicConfig(format='%(asctime)s %(name)s %(levelno)s %(filename)s ''%(lineno)d %(funcName)s %(message)s', level=logging.DEBUG)x.info = 1logging.info("执行了{},结果是{},{},{}".format(cls.__name__,x, args, kwargs))return inwapperclass User:info = None@funcdef name(self, name, name1, age):# return name, name1, agepass
if __name__ == '__main__':u = User()u.name("清安","ANAN",age=18)print(u.info)
# 1
# 2023-03-02 09:15:36,640 root 20 ceshi_test.py 75 inwapper 执行了name,结果是<__main__.User object at 0x0000021B20A2F5B0>,('清安', 'ANAN'),{'age': 18}
❝显而易见,赋值成功。再来看看对其他函数赋值。
❞
def func(cls):def inwapper(x, *args, **kwargs):logging.basicConfig(format='%(asctime)s %(name)s %(levelno)s %(filename)s ''%(lineno)d %(funcName)s %(message)s', level=logging.DEBUG)x.Info("QA",18)logging.info("执行了{},结果是{},{},{}".format(cls.__name__,x, args, kwargs))return inwapperclass User:info = None@funcdef name(self, name, name1, age):# return name, name1, agepassdef Info(self,name,age):print("我是{},今年{}".format(name,age))if __name__ == '__main__':u = User()u.name("清安","ANAN",age=18)
# 2023-03-02 09:19:26,910 root 20 ceshi_test.py 75 inwapper 执行了name,结果是<__main__.User object at 0x00000232FF01F5B0>,('清安', 'ANAN'),{'age': 18}
# 我是QA,今年18
示例8-伪装
from functools import wrapsdef timer(value):def func(fun):# @wraps(fun)def inner(*args,**kwargs):res = fun()print(value)print(inner.__name__)return resreturn innerreturn func@timer("QA")
def run():passif __name__ == '__main__':run()
❝伪装装饰器,让装饰器函数名称指向运行函数名。
❞
此外还有一些用法,此处就不再阐述,学习完上述的示例后,你是否能自己写出一个像样的装饰器呢?
相关文章:
Python装饰器的具体实用示例
示例1:普通装饰器 def name(n):def func(x):res n(xx)return resreturn funcname def run(x): # run name(run)print(x)if __name__ __main__:run(1) # 2def name(n):def func(*x):res n(xx)return resreturn funcname def run(x): # run name(run)pr…...
谈谈我对Retrofit源码的理解
文章目录一、Retrofit简介二、使用介绍2.1 app / build.gradle添加依赖2.2 创建 Retrofit 实例2.3 创建 API 接口定义文件2.4 使用 Retrofit 进行网络请求三、源码分析3.1 创建 Retrofit 实例: 建造者模式创建Retrofit3.2 实例化API接口: 动态代理模式3.3 获取Observable返回值…...
八股文(三)
目录 一、 如何理解原型与原型链 二、 js继承 三、 vuex的使用 1.mutation和action的区别 mutation action 2.Vuex都有哪些API 四、 前端性能优化方法 五、 类型判断 题目 (1)typeof判断哪个类型会出错(即结果不准确)&…...
2023最新实施工程师面试题
1、两电脑都在同一个网络环境中,A 电脑访问不到 B 电脑的共享文件。此现象可能是哪些 方面所导致?怎样处理? 答:首先你要确定是不是在一个工作组内,只有在一个工作组内才可以共享文件,然后看一个看一看有没有防火墙之类的,然后确定文件是不是已经共享 2、 电脑开机时风扇…...
安卓逆向_6 --- JNI 和 NDK
Java 本机接口规范内容:https://docs.oracle.com/en/java/javase/19/docs/specs/jni/index.html JNI官方中文资料:https://blog.csdn.net/yishifu/article/details/52180448 NDK 官方文档:https://developer.android.google.cn/training/ar…...
Pod控制器
K8S之控制器详解#简介#在kubernetes中,按照Pod的创建方式可以将其分为两类:自主式:kubernetes直接创建出来的Pod,这种Pod删除后就没有了,也不会重建。控制器创建pod:通过Pod控制器创建的Pod,这种Pod删除之后还会自动重…...
微服务到云原生
微服务到云原生 微服务 微服务架构(Microservice Architecture)是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。 微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各…...
Spring Security 实现自定义登录和认证(1):使用自定义的用户进行认证
1 SpringSecurity 1.1 导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId> </dependency>1.2 编写配置类 在spring最新版中禁用了WebSecurityConfigurerAdapter…...
Spring Cloud(微服务)学习篇(七)
Spring Cloud(微服务)学习篇(七) 1.使用代码的方式实现流量限制规则 1.1 变更SentinelController类 1.1.1 加入的代码 //流控限制 (一个或多个资源限流), postConstruct注解的作用是保证项目一启动就会加载,// 一个rule就是一个规则PostConstructpublic void FlowRule(){Li…...
嵌入式安防监控项目——前期知识复习
目录 一、概述 二、C语言 三、数据结构 四、IO进程 五、网络 六、ARM体系结构和接口技术 七、系统移植 八、内核驱动 一、概述 我再报班之前学过51和32,不过都是自学的。报班开始先从应用层入手的,C语言和数据结构。只要是个IT专业的大学这都是必…...
SpringAOP——基础知识
AOP AOP全称是Aspect Oriented Programming 即面向切面编程,是对一类统一事务的集中处理 例如,我们的网页许多地方都需要进行登陆验证,这时就需要在很多地方添加重复的验证代码,而AOP可以集中配置需要登陆验证的地方,…...
kafka3.0安装使用
一:定义 Kafka传 统定义:Kafka是一个分布式的基于发布/订阅模式的消息队列(Message Queue),主要应用于大数据实时处理领域。 Kafka最 新定义 : Kafka是 一个开源的 分 布式事件流平台 (Event St…...
Centos7(阿里云)_安装Mysql8.0
1.安装MySQL 新人可以试用一个月的阿里云,centos7的 一开始可能确实会自带mariadb,所以可以在网上随便找个教程开始尝试安装MySQL,当然大概率出错,然后此时你的rpm下面已经有了一个版本的mysql安装包。 以我为例,随便…...
【Java】JVM
一、介绍 1.什么是JVM? JVM是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的。JVM包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。JVM屏…...
Linux 和数据库笔记-06
今日内容介绍全天内容无需立马掌握MySQL 的高级功能应用数据库设计ER模型定义: E 代表实体(数据表), R 代表联系(数据表之间对应的字段)关系常见分类一对一一对多多对多外键如果…...
MySQL面试题-事务篇
1.事务的特性(ACID) 事务(Transaction)是指一组操作被看作是一个不可分割的工作单元,这组操作要么全部执行成功,要么全部执行失败。事务的特性通常用 ACID 四个单词来描述,它们分别代表原子性&…...
Linux嵌入式开发 | 汇编驱动LED(1)
文章目录🚗 🚗Linux嵌入式开发 | 汇编驱动LED(1)🚗 🚗初始化IO🚗 🚗STM32🚗 🚗使能GPIO时钟🚗 🚗设置IO复用🚗 Ƕ…...
什么是EventLoop?怎么测试Node或页面的性能
Event Loop 机制大家应该都有了解。本文利用 EventLoop 去做一个有趣的检测node或页面性能的代码,顺便介绍了一下EventLoop,希望对大家有所帮助! Event Loop Event Loop 机制大家应该都有了解。我先重复总结一下。 Node.js 和 Javascript 的…...
1018 锤子剪刀布 1025 反转链表
现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。 输入格式: 输入第 1 行给出正整数 N(≤10 5 ),即双方交锋的次数。随后 N 行,每行给出一次交锋的信…...
卷积神经网络的原理及实现
专栏:神经网络复现目录 卷积神经网络 本章介绍的卷积神经网络(convolutional neural network,CNN)是一类强大的、为处理图像数据而设计的神经网络。 基于卷积神经网络架构的模型在计算机视觉领域中已经占主导地位,当今…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
