装饰器

2023-05-16

装饰器


由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。

>>> def now(): ... print('2015-3-25') ... >>> f = now >>> f() 2015-3-25 

函数对象有一个__name__属性,可以拿到函数的名字:

>>> now.__name__
'now'
>>> f.__name__
'now'

现在,假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:

def log(func):
    def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper 

观察上面的log,因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。我们要借助Python的@语法,把decorator置于函数的定义处:

@log
def now(): print('2015-3-25') 

调用now()函数,不仅会运行now()函数本身,还会在运行now()函数前打印一行日志:

>>> now()
call now():
2015-3-25 

@log放到now()函数的定义处,相当于执行了语句:

now = log(now)

由于log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在log()函数中返回的wrapper()函数。

wrapper()函数的参数定义是(*args, **kw),因此,wrapper()函数可以接受任意参数的调用。在wrapper()函数内,首先打印日志,再紧接着调用原始函数。

如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。比如,要自定义log的文本:

def log(text):
    def decorator(func): def wrapper(*args, **kw): print('%s %s():' % (text, func.__name__)) return func(*args, **kw) return wrapper return decorator 

这个3层嵌套的decorator用法如下:

@log('execute')
def now(): print('2015-3-25') 

执行结果如下:

>>> now()
execute now():
2015-3-25

和两层嵌套的decorator相比,3层嵌套的效果是这样的:

>>> now = log('execute')(now)

我们来剖析上面的语句,首先执行log('execute'),返回的是decorator函数,再调用返回的函数,参数是now函数,返回值最终是wrapper函数。

以上两种decorator的定义都没有问题,但还差最后一步。因为我们讲了函数也是对象,它有__name__等属性,但你去看经过decorator装饰之后的函数,它们的__name__已经从原来的'now'变成了'wrapper'

>>> now.__name__
'wrapper'

因为返回的那个wrapper()函数名字就是'wrapper',所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

不需要编写wrapper.__name__ = func.__name__这样的代码,Python内置的functools.wraps就是干这个事的,所以,一个完整的decorator的写法如下:

import functools

def log(func): @functools.wraps(func) def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper 

或者针对带参数的decorator:

import functools

def log(text): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): print('%s %s():' % (text, func.__name__)) return func(*args, **kw) return wrapper return decorator 

import functools是导入functools模块。模块的概念稍候讲解。现在,只需记住在定义wrapper()的前面加上@functools.wraps(func)即可。

转载于:https://www.cnblogs.com/LewisAAA/p/9271290.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

装饰器 的相关文章

  • ubuntu修改启动项等待时间、修改启动项顺序、更改启动内核

    目录 ubuntu修改启动项等待时间 修改启动项顺序 更改系统内核版本 ubuntu修改启动项等待时间 步骤 sudo vi etc default grub找GRUB TIMEOUT 61 10 那一行 xff0c 把10改为需要的时间即
  • 好电影推荐

    今天在网上看到一篇给大家推荐电影的帖子 xff0c 里面搜集了一些欧美电影 xff0c 有悬疑片 剧情片 动作片 恐怖片 xff0c 包括经典的 以及一些流传不是很广的 xff0c 在这里收藏一下与大家一起分享 xff1a 1 不请自来 典
  • CodeBlock无编辑器问题解决

    对于新手小白来说 xff0c 在使用CodeBlock做C语言或者C 43 43 方面的编写时 xff0c CodeBlock会出现如下情况 xff1a Can 39 t find compiler executable in your c
  • argparse—使用命令行输入,给变量赋值

    import argparse if name 61 61 39 main 39 parser 61 argparse ArgumentParser parser add argument 39 bbb 39 type 61 int def
  • 树莓派keras、TensorFlow环境安装记录

    1 安装arm版的TensorFlow xff0c 方法参考 xff1a https github com samjabrahams tensorflow on raspberry pi 2 安装keras sudo apt get ins
  • inception 论文阅读笔记

    inception V1 提出inception unit xff0c 采用多个size的卷积核对输入进行卷积 采用1x1 3x3 5x5的卷积核不是必须的 xff0c 而是为了方便 可以理解为不同大小的卷积核可以提取到图像中不同大小的特征
  • 树莓派3 raspbian系统 红外遥控器 lirc库使用笔记

    目的 xff1a 接入红外接受硬件 xff0c 使用红外遥控器控制树莓派 硬件图 xff1a 稍后补 接受口GPIO 61 18 首先安装lirc库 sudo apt get update sudo apt get install lirc
  • 树莓派设置静态IP

    vi etc dhcpcd conf 使用 vi 编辑文件 xff0c 增加下列配置项 指定接口 eth0 或者wlan0 interface wlan0 指定静态IP xff0c 24表示子网掩码为 255 255 255 0 stati
  • BGP→→

    BGP 4 提供了一套新的机制以支持无类域间路由 这些机制包括支持网络前缀的通告 取消 BGP 网络中 类 的概念 BGP 4 也引入机制支持路由聚合 xff0c 包括 AS 路径的集合 特点 BGP属于外部或域间路由协议 BGP的主要目标
  • omnet++,veins,sumo使用多应用层实现车辆和行人的模拟

    1 完成网络的搭建 xff1a 搭建一个简单的十字路口场景 xff1a 1 xff09 定义结点 xff1a 新建intersection node xml 内容如下 xff1a NOTE1 xff1a 结点属性type 61 34 tra
  • 我的2011--衣带渐宽终不悔,为伊消得人憔悴

    古今之成大事业 大学问者 xff0c 必经过三种之境界 xff1a 34 昨夜西风凋碧树 独上高楼 xff0c 望尽天涯路 34 此第一境也 34 衣带渐宽终不悔 xff0c 为伊消得人憔悴 34 此第二境也 34 众里寻他千百度 xff0
  • Java架构师面试必备题(含答案)

    第一题 xff1a 一条sql执行过长的时间 xff0c 你如何优化 xff0c 从哪些方面 xff1f 答 xff1a 1 查看sql是否涉及多表的联表或者子查询 xff0c 如果有 xff0c 看是否能进行业务拆分 xff0c 相关字段
  • 嵌入式操作系统学习(2)任务启动和任务切换

    1 前后台系统与多任务系统 熟悉嵌入式开发的同学都知道 xff0c 一般没有操作系统的程序都是在main函数有一个死循环来完成相关任务 xff0c 一些紧急的操作放在中断里来完成 xff0c 通常称作前后台系统 xff0c 如下图所示 xf
  • Could not load dynamic library ‘cupti64_101.dll‘; dlerror: cupti64_101.dll not found

    如果cuda正常安装的话应该是环境变量出了问题 我的解决方法是 xff0c 将C Program Files NVIDIA GPU Computing Toolkit CUDA v10 1 extras CUPTI lib64 xff0c
  • PC-Lint 使用中头文件包含的问题,以及VSCode中文乱码问题

    PC Lint 使用中头文件包含的问题 xff0c 以及VSCode中文乱码问题 最近使用PC Lint和VSCode时有一些小问题 xff0c 而且感觉以后也还会遇到 xff0c 在这里做一下记录 1 PC Lint 使用中头文件包含的问
  • 【Keras】Keras构建LSTM网络时的输入维度问题——可参考博客梳理

    Keras构建LSTM网络时的输入维度问题 可参考博客梳理 keras中的LSTM层 keras layers LSTM units activation 61 39 tanh 39 recurrent activation 61 39 s
  • Windows 如何查看tensorflow、Keras、CUDA版本号

    Windows 如何查看tensorflow Keras CUDA xff0c cuDNN版本号 1 查看tensorflow和keras版本号 进入cmd xff0c 执行python xff0c 然后执行下方命令 xff1a xff08
  • 物联网工程填空题库押题版

    侧重软件工程 架构设计没有 面向对象和测试均没有 三 填空题 6 物联网工程设计与实施的最后一个阶段的文档是 xff08 xff09 验收报告 8 需求分析是用来获取 xff08 xff09 并对其进行归纳整理的工程 xff0c 该过程是物
  • Word公式居中、自动编号及交叉引用

    Word公式居中 自动编号及交叉引用 本文使用 制表符 43 样式分隔符 的方法将公式居中 此外 xff0c 使用 自动图文集 实现下次公式编辑时 xff0c 可以重复利用该公式的居中样式 1 打开WORD中的 显示 隐藏编辑标记 这样是为
  • Word的”交叉引用“和”插入题注“快捷键设置

    Word的 交叉引用 和 插入题注 快捷键设置 在MSWord2019中 xff0c 可以自定义设置快捷键 方法如下 xff1a 文件 选项 自定义功能区 键盘快捷方式 xff08 自定义 xff09 具体过程如图所示 最后 xff0c 按

随机推荐

  • 【DL】图像去噪中的patch size是什么(1篇文章链接和1段代码)

    图像去噪中的patch size是什么 xff08 1篇文章链接和1段代码 xff09 写在前面 xff0c 因为自己不做图像相关的研究 xff0c 所以具体内容也不敢妄加总结 xff0c 自己感觉貌似就是将一整张图分成一块一块的进行处理
  • MacBook Air M1 + MacTex + VS Code的LaTex教程

    MacBook Air M1 43 MacTex 43 VS Code的LaTex教程 参考博文 xff1a https zhuanlan zhihu com p 107393437 分为6步 xff1a 1 安装MacTex xff1a
  • Linux进程管理-ps

    Linux进程管理 ps ps 命令的基本格式如下 xff1a root 64 localhost ps aux 查看系统中所有的进程 xff0c 使用 BS 操作系统格式 root 64 localhost ps le 查看系统中所有的进
  • Linux进程管理-常见信号

    Linux进程管理 常见信号
  • Linux进程管理-kill

    Linux进程管理 kill kill 从字面来看 xff0c 就是用来杀死进程的命令 xff0c 但事实上 xff0c 这个或多或少带有一定的误导性 从本质上讲 xff0c kill 命令只是用来向进程发送一个信号 xff0c 至于这个信
  • 联想笔记本更换固态硬盘和重装系统

    近期给自己笔记本更换了固态硬盘并且重装了系统 xff0c 在此做一下记录 更换固态硬盘 https jingyan baidu com article 48b37f8d08128f1a6564886b html 将原来机械硬盘更换为固态硬盘
  • public、private和protected的区别

    public xff1a 声明方法和属性可以被随意访问 Protected xff1a 声明的方法和属性只能被类本身和其继承子类访问 private xff1a 只能被定义属性和方法的类访问 private 是完全私有的 只有当前类中的成员
  • java.lang.ClassNotFoundException: org.springframework.jdbc.support.JdbcTransactionManager

    这个错误出现的原因可能是导入的依赖版本过低 xff0c 我的跟新到这个版本就可以了 xff0c 要添加比较新的依赖 span class token generics function span class token punctuatio
  • 关于创建React App的8个有趣事实

    来源 xff1a https medium com xff0c 作者 xff1a Jennifer Fu 翻译 xff1a 前端外文精选 你所知道的一些事情 xff0c 你可能不知道的一些事情 Create React App是搭建Reac
  • 查询“ 01 “课程比“ 02 “课程成绩高的学生的信息及课程分数

    这个是一个比较经典的sql面试题 xff0c 面试的难度挺大的 xff0c 这里我将详细讲解 xff0c 怎么使用这个方法进行查询操作 student Sid Sname Sage Ssex Sid 学生编号 Sname 学生姓名 Sage
  • localhost可以访问,使用ip地址失败

    场景 使用手机访问同一局域网内的电脑 xff0c 无法访问的问题 xff0c 前段使用的是vue的框架 Vue的框架配置 在package json中 34 dev 34 34 webpack dev server host 0 0 0 0
  • 修改Linux配置文件后,让其生效的办法

    方法一 下面这个命令 xff0c 可以使所有用户都可以生效 xff0c 但是需要重新启动服务器 xff0c 如果是企业服务器 xff0c 极其不建议重新启动 xff0c 如果允许可以重启 项目中 xff0c 这个命令一般是java通过ssh
  • 在Windows上使用nginx具体步骤

    首先下载Windows版本的nginx http nginx org en docs windows html 直接将文件解压 xff0c 然后直接在有nginx exe同级的目录下执行cmd 当然你也可以双击下图红框中的文件 xff0c
  • Linux重启nginx服务

    1 方法一 到nginx下面的sbin目录下执行 nginx s reload 2 方法二 如果第一种不生效 xff0c xff08 项目背景 xff09 实际项目不生效 xff0c 也即部署到nginx下面的vue项目 xff0c 已经更
  • 静态方法调用yml配置文件中的值

    目录 一 概念讲解二 正确方式正确方法一正确方法二 可能遇到的问题 一 概念讲解 获取配置文件的注解方式有 64 value 64 ConfigurationProperties xff0c 这两种方式遇到下列情况都会失效 xff1a 属性
  • 2022IDEA搭建springMvc项目

    springmvc项目搭建 一 创建maven项目二 Add Framework Support三 添加依赖并配置maven四 配置前端控制器 96 DispatcherServlet 96 五 配置SpringMVC XML文件六 创建c
  • Error creating bean with name ‘mySwaggerResourceProvider‘

    多种情况都会导致此错误的产生 造成原因1 依赖冲突 xff1a 当maven导入项目的依赖A与导入项目的依赖B都依赖于依赖C xff0c 如下图所示 xff0c 都依赖于guava 也就是依赖C xff0c 因为依赖A与依赖B都有依赖C的依
  • Contents have difference only in line separators

    问题描述 xff1a idea关联上git xff0c 文件更改完 xff0c 然后ctrl 43 z回退到未更改之前 xff0c 但是git上的commit还是有此文件 xff08 表示有更改的地方 xff09 xff0c 如下图所示 红
  • valid prop: custom validator check failed for prop “size“.

    问题现象 xff0c 如下图所示 解决方案 xff1a 第一步 xff1a 首先确定出问题的 vue页面 xff0c 如上图所示 xff0c 是c view business product product manage vue 文件出现的
  • 装饰器

    装饰器 由于函数也是一个对象 xff0c 而且函数对象可以被赋值给变量 xff0c 所以 xff0c 通过变量也能调用该函数 span class prompt gt gt gt span class function span class