一、概念:
从本质上讲,装饰器(B)本身就是一个函数,它的功能是用来装饰已经定义好的原函数(A)(也可以理解成为已经定义好的原函数添加一些附加的功能)。
二、原则:
1.不能修改A的源代码;
2.不能修改A的调用方式。
一句话,B对A是完全透明的,即A不知道B对A进行过附加修饰。
三、实现的基础:
1.函数即变量;
2.高阶函数;
a.将一个函数的函数名作为另一个函数的参数(即二、1);
import time def test_1(): #原函数 time.sleep(5) print("test_1") def tar(test): #高阶函数,将一个函数的函数名作为另一个函数的参数。 star_time = time.time() test() end_time = time.time() print('the func run time is %s' %(end_time - star_time)) tar(test_1) #调用,函数即变量test = test_1b.返回值中包含函数名(即二、2,不修改原函数的调用方式);
import time def test_1(): #原函数 time.sleep(5) print("test_1") def tar2(test): print("test_2") #添加新功能 return test #返回函数名 test_1 = tar2(test_1) test_1() #不改变原函数的调用方式3.嵌套函数
在一个函数的函数体中定义另一个函数。
def x(): print('x') def y(): #在一个函数的函数体内定义一个新的函数 print('y') y() x()
四、装饰器实现
经过上面的基础以后,想要做一个装饰器就简单了(运用嵌套函数结合高阶函数)。
import time def tar(test): #定义装饰器 def tar_1(): star_time = time.time() test() end_time = time.time() print('the func run time is %s' % (end_time - star_time)) return tar_1 @tar #调用装饰器,就写在原函数的前面。等同于test_1 = tar(test_1) def test_1(): #原函数 time.sleep(5) print("test_1") #test_1 = tar(test_1) test_1()一个简单的装饰器功能就实现了。
附:上面的装饰器只能实现原函数无参数的情况,如果原函数有形式参数且不止一个,并且有两个或多个原函数共用一个装饰器的时候就不能运行了。需要用到下面的方法实现:
import time def tar(test): #定义装饰器 def tar_1(*args): #将原函数的形参放到这里,*args表示不确定形参个数,可以为0也可以为多个。 star_time = time.time() test(*args) #运行原函数 end_time = time.time() print('the func run time is %s' % (end_time - star_time)) return tar_1 @tar #调用装饰器,就写在原函数的前面 def test_1(): #原函数 time.sleep(5) print("test_1") @tar def test_2(x): print("x=%s" %x) test_1() test_2('zhang')