Python之装饰器-无参装饰器

Python之装饰器-无参装饰器

装饰器介绍

1. 为何要用装饰器

  • Python 中的装饰器是一种语法糖,可以在运行时,动态的给函数或类添加功能。
  • 装饰器本质上是一个函数,使用 @ + 函数名就是可实现绑定给函数的第二个功能 。
  • 将一些通用的、特定函数的功能抽象成一个装饰器,可以重复利用这些功能

2. 什么是装饰器

  • “装饰”代指为被装饰对象添加新的功能,“器”代指器具/工具
  • 装饰器的作用:就是在不修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能。
  • 装饰器使用场景:插入日志、性能测试、事务处理、缓存、权限校验
  • 可以调用的有:函数、方法、类
  • 函数装饰器分为:无参装饰器和有参装饰,二者都是使用都是需要【名称空间+函数嵌套+闭包+函数对象的组合知识】
  • 使用“@”符号定义装饰器,前提是需要有一个函数作为工具然后被“@”装饰到其他函数头上,为这个函数添加功能

无参装饰器

  • @符号后是一个函数
  • 虽然是无参装饰器,但是@后的函数本质上是单参函数

def add(x, y):
    print(add.__name__, x, y)
    return x + y

add(4, 5)

# 此函数记录了,调用了add函数,x和y的值是什么
# 返回结果:add 4 5
# 返回结果:9
import time # 时间底层模块
print('------')
time.sleep(10)
print('******')

# 导入time模块,执行第1个print后,time.sleep(10) 休眠10秒,然后输出第2个print
# 返回结果:------
# 返回结果:******
import datetime # 导入datetime模块

start = datetime.datetime.now() # 设置start,获取当前时间

# 导入datetime模块
end = datetime.datetime.now() # 设置end,获取当前时间

# end变量在下一个代码块中执行,稍微等几秒错开时间。
start, end 

# 记录的两个时间戳,用于记录开始时间和结束时间
# 返回结果:(datetime.datetime(2024, 3, 23, 11, 4, 2, 337816), datetime.datetime(2024, 3, 23, 11, 4, 4, 518772))
(end - start).total_seconds() # total.seonds 总秒数

# end 减去 start 获取运行的秒数
# 返回结果:2.180956
def add(x, y):
    #print(add.__name__, x, y) # 这个只能记录add,sub呢?
    #time.sleep(2) # 修秒2秒
    return x + y

def logger(fn):
    ret = fn(4, 5)
    return ret

logger(add)

# base版,基于这版,增加功能、
# 返回结果:9
def add(x, y):
    #print(add.__name__, x, y) # 这个只能记录add,sub呢?
    #time.sleep(2)
    return x + y

def logger(fn, x, y):
    
    ret = fn(x, y)
    return ret

logger(add, 4, 5)

# 返回结果:9
def add(x, y):
    #print(add.__name__, x, y) # 你这个只能记录add,sub呢?
    #time.sleep(2)
    return x + y

def logger(fn, x, y):
    print(fn.__name__, x, y) # 增加记录值
    ret = fn(x, y)
    return ret

logger(add, 4, 5)

# 返回结果:add 4 5
# 返回结果:9
def add(x, y):
    #mylog(add.__name__, x, y) # 你这个只能记录add,sub呢?
    #time.sleep(2)
    return x + y

def sub(x, y): # 可以用于多个函数
    return x - y

def logger(fn, x, y):
    print(fn.__name__, x, y) # 增加记录值
    ret = fn(x, y)
    return ret

logger(add, 4, 5)
logger(sub, 5, 6)

# 返回结果:add 4 5
# 返回结果:sub 5 6
# 返回结果:-1
def add(x, y):
    #mylog(add.__name__, x, y) # 你这个只能记录add,sub呢?
    #time.sleep(2)
    return x + y

def sub(x, y, z): # 可以用于多个函数
    return x - y - z

def logger(fn, *args, **kwargs): # 接受关键字传参,位置传参。
    print(fn.__name__, args, kwargs) # 增加记录值
    print('执行前可以做的事情,增强')
    ret = fn(*args, **kwargs)
    print('执行后可以做的事情,增强')
    return ret

logger(add, 4, y=8)
logger(sub, 5, 6, z=7)

# 返回结果:add (4,) {'y': 8}
# 返回结果:执行前可以做的事情,增强
# 返回结果:执行后可以做的事情,增强
# 返回结果:sub (5, 6) {'z': 7}
# 返回结果:执行前可以做的事情,增强
# 返回结果:执行后可以做的事情,增强
# 返回结果:-8
def add(x, y):
    #mylog(add.__name__, x, y) # 你这个只能记录add,sub呢?
    #time.sleep(2)
    return x + y

def sub(x, y, z): # 可以用于多个函数
    return x - y - z

def logger(fn):
    def inner(*args, **kwargs):
        print(fn.__name__, args, kwargs) # 增加记录值
        print('执行前可以做的事情,增强')
        ret = fn(*args, **kwargs)
        print('执行后可以做的事情,增强')
        return ret
    return inner

logger(add)(4, y=8)
#logger(sub, 5, 6, z=7)

# 返回结果:add (4,) {'y': 8}
# 返回结果:执行前可以做的事情,增强
# 返回结果:执行后可以做的事情,增强
# 返回结果:12
def add(x, y):
    #time.sleep(2)
    return x + y

def sub(x, y, z): # 可以用于多个函数
    return x - y - z

def logger(fn):
    def inner(*args, **kwargs):
        print('执行前可以做的事情,增强', fn.__name__, args, kwargs)
        ret = fn(*args, **kwargs)
        print('执行后可以做的事情,增强')
        return ret
    return inner

logger(add)(4, y=8)
#logger(sub, 5, 6, z=7)

# 返回结果:执行前可以做的事情,增强 add (4,) {'y': 8}
# 返回结果:执行后可以做的事情,增强
# 返回结果:12
def add(x, y):
    #time.sleep(2)
    return x + y

def sub(x, y, z): # 可以用于多个函数
    return x - y - z

def logger(fn): # fn add
    def inner(*args, **kwargs):
        print('执行前可以做的事情,增强', fn.__name__, args, kwargs)
        ret = fn(*args, **kwargs) # fn(4, y=8) add(4, y=8)
        print('执行后可以做的事情,增强')
        return ret
    return inner

t = logger(add) # t = inner
print(t(4, y=8)) # inner(4, y=8)

# 返回结果:执行前可以做的事情,增强 add (4,) {'y': 8}
# 返回结果:执行后可以做的事情,增强
# 返回结果:12
def add(x, y):
    #time.sleep(2)
    return x + y

def logger(fn): # fn add
    def inner(*args, **kwargs):
        print('执行前可以做的事情,增强', fn.__name__, args, kwargs)
        ret = fn(*args, **kwargs) # fn(4, y=8) add(4, y=8)
        print('执行后可以做的事情,增强')
        return ret
    return inner

#t = logger(add) # t = inner
#print(t(4, y=8)) # inner(4, y=8)

add = logger(add)
print(add(4, 5))

# 返回结果:执行前可以做的事情,增强 add (4, 5) {}
# 返回结果:执行后可以做的事情,增强
# 返回结果:9

请添加图片描述

def add(x, y):
    #time.sleep(2)
    return x + y

def logger(fn): # fn add
    def inner(*args, **kwargs):
        print('执行前可以做的事情,增强', fn.__name__, args, kwargs)
        ret = fn(*args, **kwargs) # fn(4, y=8) add(4, y=8)
        print('执行后可以做的事情,增强')
        return ret
    return inner

#t = logger(add) # t = inner
#print(t(4, y=8)) # inner(4, y=8)
print(hex(id(add))) # 打印add的id值
add = logger(add)
print(add(4, 5))
print(add.__closure__) # 查看add的closure中记录闭包

# 返回结果:0x10954fd80
# 返回结果:执行前可以做的事情,增强 add (4, 5) {}
# 返回结果:执行后可以做的事情,增强
# 返回结果:9
# 返回结果:(<cell at 0x1083e3d90: function object at 0x10954fd80>,)
def logger(fn): # fn add
    def inner(*args, **kwargs):
        print('执行前可以做的事情,增强', fn.__name__, args, kwargs)
        ret = fn(*args, **kwargs) # fn(4, y=8) add(4, y=8)
        print('执行后可以做的事情,增强')
        return ret
    return inner

@logger # 装饰器 #等价式, add = logger(add) # logger应该等效为单参函数
def add(x, y):
    #time.sleep(2)
    return x + y

#t = logger(add) # t = inner
#print(t(4, y=8)) # inner(4, y=8)
#add = logger(add)
print(add(4, 5))

# @装饰器语法,@标识符,把这一行下面一行的def定义的标识符作为其实参传入,返回值覆盖了下面这个标识符
# 返回结果:执行前可以做的事情,增强 add (4, 5) {}
# 返回结果:执行后可以做的事情,增强
# 返回结果:9
def logger(fn): 
    def inner(*args, **kwargs):
        print('执行前可以做的事情,增强', fn.__name__, args, kwargs)
        ret = fn(*args, **kwargs) 
        print('执行后可以做的事情,增强')
        return ret
    return inner

@logger # 装饰器 #等价式, add = logger(add) # logger应该等效为单参函数
def add(x, y):
    #time.sleep(2)
    return x + y

print(add(4, 5)) # 非侵入代码,完成了功能,并且好像从来没有装饰过一样
print(add.__name__) #add实际是inner

# 返回结果:执行前可以做的事情,增强 add (4, 5) {}
# 返回结果:执行后可以做的事情,增强
# 返回结果:9
# 返回结果:inner
def logger(wrapped): 
    def wrapper(*args, **kwargs):
        print('执行前可以做的事情,增强', wrapped.__name__, args, kwargs)
        ret = wrapped(*args, **kwargs) 
        print('执行后可以做的事情,增强')
        return ret
    return wrapper

@logger # 装饰器 #等价式, add = logger(add) # logger应该等效为单参函数
def add(x, y):
    #time.sleep(2)
    return x + y

print(add(4, 5)) # 非侵入代码,完成了功能,并且好像从来没有装饰过一样
print(add.__name__)

# 返回结果:执行前可以做的事情,增强 add (4, 5) {}
# 返回结果:执行后可以做的事情,增强
# 返回结果:9
# 返回结果:wrapper
def logger(wrapped): 
    def wrapper(*args, **kwargs):
        start = datetime.datetime.now()
        ret = wrapped(*args, **kwargs) 
        delta = (datetime.datetime.now() - start).total_seconds()
        print("{} tooks {}s.".format(wrapped.__name__, delta))
        return ret
    return wrapper

@logger # 装饰器 #等价式, add = logger(add) # logger应该等效为单参函数
def add(x, y):
    time.sleep(2)
    return x + y

print(add(4, 5)) # 非侵入代码,完成了功能,并且好像从来没有装饰过一样
print(add.__name__) 

# 返回结果:add tooks 2.002051s.
# 返回结果:9
# 返回结果:wrapper

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

InstructGPT的流程介绍

1. Step1&#xff1a;SFT&#xff0c;Supervised Fine-Tuning&#xff0c;有监督微调。顾名思义&#xff0c;它是在有监督&#xff08;有标注&#xff09;数据上微调训练得到的。这里的监督数据其实就是输入Prompt&#xff0c;输出相应的回复&#xff0c;只不过这里的回复是人工…

python5:基于多进程的并发编程、基于协程的并发编程的学习笔记

进程 为什么要使用多进程&#xff1f;——GIL的存在&#xff0c;多线程实际不是并发执行 将任务分为两类&#xff1a;IO密集型&#xff08;多线程&#xff09;CPU密集型&#xff08;多进程&#xff09; 多进程的基本用法 concurrent.futures.process.ProcessPoolExecutor#进…

李清照想老公了,人比黄花瘦

年轻时的风光无限&#xff0c;中年时的颠沛流离&#xff0c;晚年时的孤独寂寞&#xff0c;李清照的一生跌宕起伏&#xff0c;十分凄惨。 北宋的国破家亡&#xff0c;让李清照从活泼可爱的少女成为孤独的老妇人。 一、少女情思 少女时期&#xff0c;李清照有一次去游玩&#…

【Linux】误删除/home家目录怎么办? -- 此时ssh连接登录的就是此普通用户

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…

Windows系统安装VNC客户端结合内网穿透实现公网远程连接Deepin桌面

文章目录 1. 安装x11vnc2. 本地远程连接测试3. Deepin安装Cpolar4. 配置公网远程地址5. 公网远程连接Deepin桌面6. 固定连接公网地址7. 固定公网地址连接测试 x11vnc是一种在Linux系统中实现远程桌面控制的工具&#xff0c;它的原理是通过X Window系统的协议来实现远程桌面的展…

AJAX-综合

文章目录 同步代码和异步代码回调函数地狱解决回调函数地狱Promise-链式调用async函数和awaitasync函数和await-捕获错误 事件循环宏任务与微任务Promise.all静态方法 同步代码和异步代码 同步代码&#xff1a;逐步执行&#xff0c;需原地等待结果后&#xff0c;才继续向下执行…

深入探索C语言动态内存分配:释放你的程序潜力

&#x1f308;大家好&#xff01;我是Kevin&#xff0c;蠢蠢大一幼崽&#xff0c;很高兴你们可以来阅读我的博客&#xff01; &#x1f31f;我热衷于分享&#x1f58a;学习经验&#xff0c;&#x1f3eb;多彩生活&#xff0c;精彩足球赛事⚽ &#x1f31f;感谢大家的支持&#…

【Java程序设计】【C00341】基于Springboot的药品管理系统(有论文)

基于Springboot的药品管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 项目获取 &#x1f345;文末点击卡片获取源码&#x1f345; 开发环境 运行环境&#xff1a;推荐jdk1.8&#xff1b; 开发工具&#xff1a;eclipse以及idea&…

力扣刷题31-33(力扣 0024/0070/0053)

今日题目&#xff1a; 24. 两两交换链表中的节点 题目&#xff1a;给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09; 思路&…

BOM 浏览器对象模型

文章目录 1. BOM 概述2.window 对象的常见事件窗口加载事件调整窗口大小事件 3.定时器setTimeout() 定时器案例&#xff1a;5秒后自动关闭的广告停止 setTimeout() 定时器setInterval() 定时器案例&#xff1a;倒计时停止 setInterval() 定时器案例&#xff1a;发送短信this 4.…

亚马逊云科技:企业如何开启生成式AI之旅?

如果要评选最近两年全球科技行业最热门的细分领域&#xff0c;那么生成式AI绝对会以遥遥领先的票数成为当仁不让的冠军。 然而眼见生成式AI发展得如火如荼&#xff0c;越来越多的企业却陷入了深深的焦虑&#xff1a;应该如何开启生成式AI之旅&#xff1f;又该怎样搭建大模型&am…

MySQL进阶-----Linux系统安装MySQL

目录 前言 一、准备工作 1. 准备一台Linux服务器 2. 下载Linux版MySQL安装包 3. 上传MySQL安装包 二、安装操作指令 1. 创建目录,并解压 2.安装mysql的安装包 三、开启mysql与密码修改 1.启动MySQL服务 2. 查询自动生成的root用户密码 3.修改root用户密码 四、创…

机器学习:智能时代的核心引擎

目录 一、什么是机器学习 二、监督学习 三、无监督学习 四、半监督学习 五、强化学习 一、什么是机器学习 机器学习是人工智能的一个分支&#xff0c;它主要基于计算机科学&#xff0c;旨在使计算机系统能够自动地从经验和数据中进行学习并改进&#xff0c;而无需进行明确…

MySQL下载及安装过程

MySQl 5.7 安装图解 目录 MySQl 5.7 安装图解 第一步 安装包 第二步 Mysql协议 第三步 安装前检查 第四步 安装 第五步 产品配置 第六步 安装完成 第一步 安装包 双击安装包文件 进行安装 第二步 Mysql协议 同意Mysql协议 , 选择 Server Only安装Mysql服务器即可 …

C语言 预处理器 注释 基本案例讲解

上文 程序设计语言与C语言发展 我们简述了 计算机语言的发展 以及编程语言与指令的概念 那么 今天 我们就来 初始C语言 并完成 第一个C语言案例 这里 我们需要完成 C语言 Hello World案例 以及 C语言程序举例 任何编程语言 开始的案例 都是 Hello World 所以说 Hello World 是…

Flutter 事件传递简单概述、事件冒泡、事件穿透

前言 当前案例 Flutter SDK版本&#xff1a;3.13.2 本文对 事件传递只做 简单概述&#xff0c;主要讲解&#xff0c;事件传递过程中可能遇到的问题解决&#xff0c;比如 事件冒泡、事件穿透&#xff1b; 不是我偷懒&#xff0c;是自认为没有这几位写的详细、仔细&#xff0c…

【Langchain-Chatchat】部署ChatGLM3-6B-32K教程

介绍 Langchain-Chatchat这个框架可以帮助我们更容易的部署大语言模型&#xff0c;之前也写过ChatGLM传统的部署教程&#xff0c;有兴趣的可以参考 【ChatGLM3】第三代大语言模型多GPU部署指南【ChatGLM2-6B】从0到1部署GPU版本 借助Langchain-Chatchat框架&#xff0c;可以…

入门linux之Ubuntu学习

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1、介绍Ubuntu2、虚拟机目录解析3、常用指令ls&#xff1a;罗列当前目录文件信息对ls -l 的结果解析1.第一个字符2.每三个字符&#xff08;第一个字符后&#x…

新店开通后要做什么?一定要先做这几个设置,不然会影响店铺流量

大家好&#xff0c;我是电商花花。 新手做店如果没有一个完整的做店思路&#xff0c;很容易迷茫&#xff0c;没有方向&#xff0c;没有步骤&#xff0c;做完上一步不知道下一步该去干嘛。 今天给大家讲一下在开店后一定要做的几项基础搭建。 1、绑定官方账户 开店后在店铺后…