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)是一类强大的、为处理图像数据而设计的神经网络。 基于卷积神经网络架构的模型在计算机视觉领域中已经占主导地位,当今…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
