7.Python中的装饰器(Decorator)
《Python编程的术与道:Python语言进阶》视频课程
《Python编程的术与道:Python语言进阶》视频课程链接:https://edu.csdn.net/course/detail/28618
装饰器 (Decorator)
装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外的功能。装饰器的返回值也是一个函数/类对象。有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码到装饰器中并继续重用。
它经常用于有切面(aspect)需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。
def div(a,b):print(a/b)
div(2,4)
0.5
def div(a,b):if a<b:a,b = b,aprint(a/b)
div(2,4)
2.0
def div(a,b):print(a/b)def smart_div(func):def inner(a,b):if a<b:a,b = b,areturn func(a,b)return inner
div_new = smart_div(div)div_new(2,4)
2.0
简单的装饰器
装饰器包装一个函数,修改其行为。
def my_decorator(func):def wrapper():print("Something is happening before the function is called.")func()print("Something is happening after the function is called.")return wrapperdef say_whee():print("Whee!")
say_whee = my_decorator(say_whee)
say_whee()
Something is happening before the function is called.
Whee!
Something is happening after the function is called.
语法糖 (Syntactic Sugar):
Python允许通过@
符号以更简单的方式使用装饰器。 下面的示例与上面的装饰器示例完全相同:
def my_decorator(func):def wrapper():print("Something is happening before the function is called.")func()print("Something is happening after the function is called.")return wrapper@my_decorator
def say_whee():print("Whee!")
say_whee()
Something is happening before the function is called.
Whee!
Something is happening after the function is called.
因此,@my_decorator
只是表示say_whee = my_decorator(say_whee)
的一种简单方法。 这是将一个装饰器应用于一个函数的方法。
装饰器中@functools.wraps作用
装饰器在运行期对函数进行一些外部功能的扩展。但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下比如测试时会导致一些问题。Python 通过 functool.wraps
为我们解决了这个问题:在编写装饰器时,在实现前加入 @functools.wraps(func)
可以保证装饰器不会对被装饰函数造成影响。主要是不改变使用装饰器原有函数的结构(如__name__
, __doc__
)
不使用@wraps装饰器时,__name__
和__doc__
输出的内容
def decorator(func):"""this is decorator __doc__"""def wrapper(*args, **kwargs):"""this is wrapper __doc__"""print("this is wrapper method")return func(*args, **kwargs)return wrapper@decorator
def test():"""this is test __doc__"""print("this is test method")print("__name__: ", test.__name__)
print("__doc__: ", test.__doc__)
__name__: wrapper
__doc__: this is wrapper __doc__
对test()方法进行装饰时候,实际上是调用test = decorator(test)
返回的是wrapper方法的引用,也就是让test指向了wrapper方法,所以调用test.__name__
, 实际上是wrapper.__name__
,这可能会造成后面查找该方法的名字和注释的时候会得到装饰器的内嵌函数的名字和注释。
使用@wraps装饰器解决这个问题
from functools import wraps
def decorator(func):"""this is decorator __doc__"""@wraps(func)def wrapper(*args, **kwargs):"""this is wrapper __doc__"""print("this is wrapper method")return func(*args, **kwargs)return wrapper@decorator
def test():"""this is test __doc__"""print("this is test method")print("__name__: ", test.__name__)
print("__doc__: ", test.__doc__)
__name__: test
__doc__: this is test __doc__
import functoolsdef decorator(func):@functools.wraps(func)def wrapper_decorator(*args, **kwargs):# Do something beforevalue = func(*args, **kwargs)# Do something afterreturn valuereturn wrapper_decorator
计时函数
首先创建一个@timer
装饰器。 它将测量一个函数执行所需的时间并将时间打印到控制台。
import functools
import timedef timer(func):"""Print the runtime of the decorated function"""@functools.wraps(func)def wrapper_timer(*args, **kwargs):start_time = time.perf_counter() # 1value = func(*args, **kwargs)end_time = time.perf_counter() # 2run_time = end_time - start_time # 3print(f"Finished {func.__name__!r} in {run_time:.4f} secs")return valuereturn wrapper_timer@timer
def waste_some_time(num_times):for _ in range(num_times):sum([i**2 for i in range(10000)])
waste_some_time(1)
Finished 'waste_some_time' in 0.0049 secs
waste_some_time(999)
Finished 'waste_some_time' in 3.0510 secs
7.Python中的装饰器(Decorator)相关推荐
- python中的装饰器decorator
python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x):return ...
- python装饰器原理-python 中的装饰器及其原理
装饰器模式 此前的文章中我们介绍过装饰器模式: 装饰器模式中具体的 Decorator 实现类通过将对组建的请求转发给被装饰的对象,并在转发前后执行一些额外的动作来修改原有的部分行为,实现增强 Com ...
- python类装饰器详解-python 中的装饰器详解
装饰器 闭包 闭包简单的来说就是一个函数,在该函数内部再定义一个函数,并且这个内部函数用到了外部变量(即是外部函数的参数),最终这个函数返回内部函数的引用,这就是闭包. def decorator(p ...
- 装饰器的注意事项python_python中的装饰器decorator
python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: deff1(x):returnx ...
- python编写装饰器_写python中的装饰器
python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) 1 de ...
- [转载]理解PYTHON中的装饰器
[翻译]理解PYTHON中的装饰器 来源stackoverflow上的问题 链接 python的函数是对象 要理解装饰器,首先,你必须明白,在python中,函数是对象. 这很重要. 简单例子来理解为 ...
- 为什么说想到Python中的装饰器是天才
为什么说想到Python中的装饰器是天才 只需一个@符号就能分析.测试和重复使用你的代码 带着魔杖的仙女在Python代码中飞舞 软件中有没有什么是神奇的小魔法? 有,装饰器却非常接近! 如果说有一件 ...
- python中的装饰器(基础装饰器)
文章目录 一 前置知识-高阶函数,闭包 1. 高阶函数 2. 闭包 二 函数装饰器 1. 什么是装饰器(原理)? 2. 装饰器的实现 3. 何时执行装饰器 4. wraps方法 三 类装饰器 一 前置 ...
- python中的装饰器有哪些-python 装饰器以及开发中常用的例子
有时候我们想为多个函数,同意添加某一种功能,比如及时统计,记录日志,缓存运算结果等等,而又不想改变函数代码 那就定义装饰器函数,用它来生成一个在原函数基础添加了新功能的函数,代替原函数 参考金角大王的 ...
- python装饰器-python中的装饰器常用于哪些应用场景
最新回答 2019-12-08回答 所谓装饰器就是把函数包装一下,为函数添加一些附加功能,装饰器就是一个函数,参数为被包装的函数,返回包装后的函数:你可以试下: de d(p): de _d(*arg ...
最新文章
- 一图读懂丨2019新型冠状病毒,你需要知道什么?
- php 中curd表达啥,CURD语句的基本语法和PDO中操作数据表的基本步骤实例演示增删改查命令 2019年07月24日 23时10分...
- SpringMVC之源码分析--HandlerMapping(一)
- ADO之connection
- Redis各特性的应用场景
- ThreadLocal就是这么简单
- C语言,利用条件语句判断数的奇偶性。
- 你真的会用Gson吗?Gson使用指南(三)
- 新手tiktok怎么做?海外tiktok怎么赚钱!
- 【XLPNet车牌识别算法】第一章 序
- 【Python学习】打印n位内从1到最大的整数
- 基于BERT-PGN模型的中文新闻文本自动摘要生成
- 『Java CVE』CVE-2022-34169: Xalan-J XSLT整数截断漏洞PoC结构再浅析
- java故事之致敬坚持梦想的人
- 谷歌裁员1.2万人,CEO年薪达15亿,网友:“地表最强 CEO !”
- 如何在vscode、remix中结合hardhat编译部署合约
- 视频压缩编码技术概述
- 求二维形状渐变的算法
- Coinbase 上市,说唱歌手 Nas 或将净赚 1 亿美元
- Mac自带文本编辑器TextEdit编辑大文件后打不开