当前位置: 首页 > news >正文

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&#xff1a;普通装饰器 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 四、 前端性能优化方法 五、 类型判断 题目 &#xff08;1&#xff09;typeof判断哪个类型会出错&#xff08;即结果不准确&#xff09;&…...

2023最新实施工程师面试题

1、两电脑都在同一个网络环境中,A 电脑访问不到 B 电脑的共享文件。此现象可能是哪些 方面所导致?怎样处理? 答:首先你要确定是不是在一个工作组内,只有在一个工作组内才可以共享文件,然后看一个看一看有没有防火墙之类的,然后确定文件是不是已经共享 2、 电脑开机时风扇…...

安卓逆向_6 --- JNI 和 NDK

Java 本机接口规范内容&#xff1a;https://docs.oracle.com/en/java/javase/19/docs/specs/jni/index.html JNI官方中文资料&#xff1a;https://blog.csdn.net/yishifu/article/details/52180448 NDK 官方文档&#xff1a;https://developer.android.google.cn/training/ar…...

Pod控制器

K8S之控制器详解#简介#在kubernetes中&#xff0c;按照Pod的创建方式可以将其分为两类&#xff1a;自主式:kubernetes直接创建出来的Pod&#xff0c;这种Pod删除后就没有了&#xff0c;也不会重建。控制器创建pod:通过Pod控制器创建的Pod&#xff0c;这种Pod删除之后还会自动重…...

微服务到云原生

微服务到云原生 微服务 微服务架构&#xff08;Microservice Architecture&#xff09;是一种架构概念&#xff0c;旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。 微服务是一种架构风格&#xff0c;一个大型复杂软件应用由一个或多个微服务组成。系统中的各…...

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&#xff0c;不过都是自学的。报班开始先从应用层入手的&#xff0c;C语言和数据结构。只要是个IT专业的大学这都是必…...

SpringAOP——基础知识

AOP AOP全称是Aspect Oriented Programming 即面向切面编程&#xff0c;是对一类统一事务的集中处理 例如&#xff0c;我们的网页许多地方都需要进行登陆验证&#xff0c;这时就需要在很多地方添加重复的验证代码&#xff0c;而AOP可以集中配置需要登陆验证的地方&#xff0c;…...

kafka3.0安装使用

一&#xff1a;定义 Kafka传 统定义&#xff1a;Kafka是一个分布式的基于发布/订阅模式的消息队列&#xff08;Message Queue&#xff09;&#xff0c;主要应用于大数据实时处理领域。 Kafka最 新定义 &#xff1a; Kafka是 一个开源的 分 布式事件流平台 &#xff08;Event St…...

Centos7(阿里云)_安装Mysql8.0

1.安装MySQL 新人可以试用一个月的阿里云&#xff0c;centos7的 一开始可能确实会自带mariadb&#xff0c;所以可以在网上随便找个教程开始尝试安装MySQL&#xff0c;当然大概率出错&#xff0c;然后此时你的rpm下面已经有了一个版本的mysql安装包。 以我为例&#xff0c;随便…...

【Java】JVM

一、介绍 1.什么是JVM? JVM是一种用于计算设备的规范&#xff0c;它是一个虚构出来的机器&#xff0c;是通过在实际的计算机上仿真模拟各种功能实现的。JVM包含一套字节码指令集&#xff0c;一组寄存器&#xff0c;一个栈&#xff0c;一个垃圾回收堆和一个存储方法域。JVM屏…...

Linux 和数据库笔记-06

今日内容介绍全天内容无需立马掌握MySQL 的高级功能应用数据库设计ER模型定义: E 代表实体(数据表), R 代表联系(数据表之间对应的字段)![image-20200530092701017](Linux 和数据库 day06 随堂笔记.assets/image-20200530092701017.png)关系常见分类一对一一对多多对多外键如果…...

MySQL面试题-事务篇

1.事务的特性&#xff08;ACID&#xff09; 事务&#xff08;Transaction&#xff09;是指一组操作被看作是一个不可分割的工作单元&#xff0c;这组操作要么全部执行成功&#xff0c;要么全部执行失败。事务的特性通常用 ACID 四个单词来描述&#xff0c;它们分别代表原子性&…...

Linux嵌入式开发 | 汇编驱动LED(1)

文章目录&#x1f697; &#x1f697;Linux嵌入式开发 | 汇编驱动LED&#xff08;1&#xff09;&#x1f697; &#x1f697;初始化IO&#x1f697; &#x1f697;STM32&#x1f697; &#x1f697;使能GPIO时钟&#x1f697; &#x1f697;设置IO复用&#x1f697; &#x1f6…...

什么是EventLoop?怎么测试Node或页面的性能

Event Loop 机制大家应该都有了解。本文利用 EventLoop 去做一个有趣的检测node或页面性能的代码&#xff0c;顺便介绍了一下EventLoop&#xff0c;希望对大家有所帮助&#xff01; Event Loop Event Loop 机制大家应该都有了解。我先重复总结一下。 Node.js 和 Javascript 的…...

1018 锤子剪刀布 1025 反转链表

现给出两人的交锋记录&#xff0c;请统计双方的胜、平、负次数&#xff0c;并且给出双方分别出什么手势的胜算最大。 输入格式&#xff1a; 输入第 1 行给出正整数 N&#xff08;≤10 5 &#xff09;&#xff0c;即双方交锋的次数。随后 N 行&#xff0c;每行给出一次交锋的信…...

卷积神经网络的原理及实现

专栏&#xff1a;神经网络复现目录 卷积神经网络 本章介绍的卷积神经网络&#xff08;convolutional neural network&#xff0c;CNN&#xff09;是一类强大的、为处理图像数据而设计的神经网络。 基于卷积神经网络架构的模型在计算机视觉领域中已经占主导地位&#xff0c;当今…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 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 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

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日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...