如何实现一个python函数装饰器(Decorator)
作者:半杯茶的小酒杯 发布时间:2023-12-02 19:38:37
装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。它经常用于为已有函数/类添加记录日志、计时统计、性能测试等。
首先定义一个倒计时函数,这个函数的功能非常简单,就是把n从当前值减少到0。
def countdown(n):
while n > 0:
print('time' + str(n))
n -= 1
print(countdown.__name__)
程序输出:
countdown
1.为函数增加一个日志装饰器
假设现在要增强countdown的功能,在函数调用前后自动打印日志,又不想修改函数自身的功能。这种在代码运行期间动态增加功能的方式,称之为装饰器(Decorator)。
能打印日志的decorator,可以定义如下:
def log(func):
def wrapper(*args, **kw):
print('call %s().' % func.__name__)
return func(*args, **kw)
return wrapper
然后我们借助Python的@语法,把decorator置于函数的定义处:
@log
def countdown(n):
while n > 0:
print('time:' + str(n))
n -= 1
countdown(10)
程序输出:
call countdown().
time:10
time:9
time:8
time:7
time:6
time:5
time:4
time:3
time:2
time:1
但此时我们再打印函数的name:
print(countdown.__name__)
程序输出:
wrapper
我们发现函数的元数据信息变了,这显然不是我们想要的结果。
2. 在装饰器中拷贝元数据
为了把函数的元数据信息都保留下来,我们可以直接使用Python提供的functools库中的@wraps装饰器。
from functools import wraps
def log(func):
@wraps(func)
def wrapper(*args, **kw):
print('call %s().' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def countdown(n):
while n > 0:
print('time:' + str(n))
n -= 1
print(countdown.__name__)
程序输出:
countdown
3.为函数增加一个计时装饰器
添加函数装饰器的方法已经讲清楚了,现在再实现一个完整的函数计时耗时装饰器。
import time
from functools import wraps
def TimeCost(func):
@wraps(func)
def wrapper(*arg, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end - start)
return result
return wrapper
@TimeCost
def countdown(n):
while n > 0:
print('time:' + str(n))
n -= 1
countdown(10000)
函数输出:
('countdown', 0.0004801750183105469)
参考资料:
https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584
Python Cookbook中文版
来源:http://www.banbeichadexiaojiubei.com/index.php/2020/10/11/%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AApython%E5%87%BD%E6%95%B0%E8%A3%85%E9%A5%B0%E5%99%A8decorator/?utm_source=tuicool&utm_medium=referral
猜你喜欢
- 1、settings.INSTALLED_APPS下添加:django.contrib.staticfiles2、settings.py下添
- 错误代码错误消息说 明ASP0100Out of memory内存不足(不能分配要求的内存)ASP0101Unexpected
- 如果我们希望在网页的不同角落里放置不重复平铺的背景图,该怎么办呢?比如网页的背景要如图所示,并要求在不
- logging日志模块:是用来记录日志的模块,一般记录用户在软件中的操作使用方法:模板直接拿来用,手动修改# logging的配置信息(模板
- 作为一名网站开发WEB前端工程师,对自己开发的网站项目应该尽可能地对其性能进行优化,现在互联网上搜索到的网站性能优化多是翻译转载自 Yaho
- 空白双边距是一个极容易误解的CSS特性.它不是CSS的bug,但如果我们一旦误解,将会给你带来很多麻烦.先看如下demo代码:<!do
- 模板的继承完美在写html的时候会发现,自己多个html文件中又好多东西是一样的,包括静插件的引入 还有有些简单的css样式都不需要修改,这
- 目录一、IPO模型 二、基本输入 - input()函数1、函数格式2、参数说明3、实例演示(1)接收字符串数据(2)接收整型数据
- 代码如下:CREATE TABLE [dbo].[TbGuidTable]( [TableName] [varchar](50) NOT N
- SQL Server2005扩展函数已经不是一件什么新鲜的事了,但是我看网上的大部分都是说聚合函数,例子也比较浅,那么这里就讲讲我运用扩展函
- uni-simple-router专为uniapp打造的路由器,和uniapp深度集成通配小程序、App和H5端H5能完全使用vue-rou
- 介绍godep是解决包依赖的管理工具,目前最主流的一种,原理是扫描记录版本控制的信息,并在go命令前加壳来做到依赖管理godep 建议在 g
- 本文实例讲述了Python + Requests + Unittest接口自动化测试。分享给大家供大家参考,具体如下:1. 介绍下pytho
- 1. 打开FrontPage 2003,点击“文件→新建→新建网站→其他网站模板”,然后选择“数据库界面向导”,给定网站路径后,单击[确定]
- 由于最近在处理shp文件,想要跳出arcpy的限制,所以打算学习一下pyshp包的使用方法。在使用《Python地理空间分析指南(第2版)》
- 今天我要为大家介绍的是XPath,XPath是导航和查询XML文档的语言。我们从一个函数开始。UpdateXML()函数我们已经花了很多时间
- 【原文地址】New "Orcas" Language Feature: Query Syntax 【原文发表日期】 Sa
- 上一篇已经介绍了celery的基本知识,本篇以一个小项目为例,详细说明django框架如何集成celery进行开发。本系列文章的开发环境:w
- 斐波那契记忆优化法:<script type="text/javascript">var fibonacci
- 关于英文的写作有一本十分著名的书,The Elements of Style(风格要素),编写程序也有一本The Elements of P