Python: 装饰器和语法糖
一、Python 装饰器
Python 装饰器本身就是一个函数,它的作用是装饰一个其他的函数,但是不改变原有的程序功能,还要增添新的功能,调用函数时的接口没有变化。比如,装修一个房子,如果不隔音,我在墙上加一层隔音板,却不能把墙拆了,换成隔音材质。
import time #导入时间模块 def index(): time.sleep(2) #时间休眠2秒 start_time = time.time() #time.time 是时间戳,指北京时间19700101 080000 起至现在的总毫秒数 index() end_time = time.time() print(end_time - start_time) #2.0136349201202393
虽然完成了计时功能,但如果函数有非常多个,那每一个函数的计时都要定义开始时间和结束时间的变量,比较繁琐。
import time #导入时间模块 def index(): time.sleep(2) #时间休眠2秒 def calculate_time(f): start_time = time.time() f() end_time = time.time() print(end_time - start_time) calculate_time(index) #2.0035324096679688
但装饰器不改变原有的函数调用接口,之前的函数是index 而现在要写上calculate_time(index),这样也是很不方便的。比如玩家在玩游戏时通常用WASD来控制上下左右,有一天如果改成了CSAV来控制,肯定就会有很多玩家放弃这个游戏,因此我们需要进一步升级程序。
import time #导入时间模块 def index(): time.sleep(2) #时间休眠2秒 def calculate_time(f): def inner(): start_time = time.time() f() end_time = time.time() print(end_time - start_time) return inner index = calculate_time(index) index() #2.0142064094543457
这样,既可以不改变接口又可以成功运行程序。
二、语法糖
在用装饰器之前还要写上 index = calculate_time(index) 这样一行代码,显然是很不方便的。这时候可以用 @calculate_time 替换 index = calculate_time(index)
import time #导入时间模块 def calculate_time(f): def inner(): start_time = time.time() f() end_time = time.time() print(end_time - start_time) return inner @calculate_time # 等价于index = calculate_time(index) 这行赋值的代码 def index(): time.sleep(2.2) #时间休眠2.2秒 index() #2.2051877975463867
举例
import time def timer(func): 统计函数运行时间的装饰器 def wrapper(): start = time.time() func() end = time.time() used = end - start print(f{func.__name__}used{used}) return wrapper @timer def step1(): print(step1.....) @timer def step2(): print(step2.....) @timer def step3(): print(step3.....) step1() step2() step3()