-
python中的装饰器
-
开放封闭原则:
- 开放:对源码的拓展是开放的。
- 封闭:对源码的修改是封闭的。
-
装饰器:完全遵循开放封闭原则,即在不改变原函数的代码以及调用方式的前提下,为其增加新的功能。(装饰器的本质是闭包)
- 举例:计算func1函数的运行效率。
def func1(): for i in range(10000): i+=1
此问题相当于为函数func1增加一个方法,可以计算函数的运行时间。用简单的time模块就可以完成,如下:
import time time.perf_counter() func1() print(f'程序运行的时间为:{time.perf_counter()}')
但这样做不满足开放封闭原则,可更改为如下:
import time def timer(f): def inner(): time.perf_counter() f() print(f'程序运行的时间为:{time.perf_counter()}') return inner func1=timer(func1) func1() #这样在不改变原函数的调用方式下为原函数增加了新的功能。即为原始的装饰器模型。在运行大型平台时非常有用。 #装饰器的本质是闭包 import time def timer(f): f=func1 #f为自由变量,指向函数func1的内存地址。 def inner(): time.perf_counter() f() print(f'程序运行的时间为:{time.perf_counter()}') return inner func1=timer(func1) func1()
但如果想要测试另一个函数(例如func3)的效率,则仍然需要增加一句语法:
func3=timer(func3)
。假设要测试的函数过多的话,就会比较麻烦。 -
原始装饰器模型的升级版本:python做了一个优化,提出了一个‘语法糖’的概念。即在编写了装饰器后,需要将装饰器代码放在所有代码的前方。
import time #装饰器函数 def timer(f): def inner(): time.perf_counter() f() print(f'程序运行的时间为:{time.perf_counter()}') return inner #当要对装饰器函数调用时,在要装饰函数的前方使用@+装饰器函数名,如下: @timer #相当于func1=timer(func1) def func1(): for i in range(10000): i+=1 func1() #此时即使有func3,也可以直接在函数前调用装饰器: @timer #会将两行并为一行读取:func3=timer(func3) def func3(): pass
-
当函数有返回值时(被装饰函数有返回值时):
import time #装饰器函数 def timer(f): def inner(): time.perf_counter() f() print(f'程序运行的时间为:{time.perf_counter()}') return inner @timer def func1(): for i in range(10000): i+=1 return i print(func1()) #None,无法打印出函数func1的返回值。
此时要对装饰器进行改进:
import time #装饰器函数 def timer(f): def inner(): time.perf_counter() r = f() #将返回值赋值给r print(f'程序运行的时间为:{time.perf_counter()}') return r #将返回值给inner函数。 return inner @timer def func1(): for i in range(10000): i+=1 return i print(func1()) #10000
加上装饰器不应该改变原函数的返回值,所有func1的返回值i应该返回给inner函数。
-
当函数有参数时(被装饰函数带参数):
import time #装饰器函数 def timer(f): def inner(*arg,**kargs): #*的聚合 time.perf_counter() r = f(*arg,**kargs) #*的打散 ,并将返回值传给inner函数。 print(f'程序运行的时间为:{time.perf_counter()}') return r #将返回值给inner函数。 return inner @timer def func1(num1,num2): for i in range(num1,num2): i+=1 return i print(func1()) #
-
标准版的装饰器:
def wrapper(f): def inner(*arg,**kargs): '''添加额外的功能:执行被装饰函数之前的操作''' ret = f(*arg,**kargs) '''添加额外的功能:执行被装饰函数之前的操作''' return ret return inner #装饰器的调用 @wrapper def func(): pass
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
JavaScript判断两个数组相等的四类方法
js如何操作video标签
React实战--利用甘特图和看板,强化Paas平
【记录】正则替换的偏方
前端下载 Blob 类型整理
抽象语法树AST必知必会
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程