python-装饰器
---恢复内容开始---
装饰器:装饰器的本质就是一个函数,其主要目的就是装饰其他函数(为其他函数添加新功能)!
装饰器的一些特性:
- 不能修改被装饰函数的源代码
- 被装饰函数的调用方式不能改变
理解以下三点:
- 函数即变量(函数名可以类比变量名,函数体可以类比变量的内容!)
- 高阶函数:
- 把一个函数的函数名作为实参传递给另外一个函数
- 函数的返回值中包含函数名
#满足两个条件之一的均称为高阶函数 # def bar(): #传递函数名作为实参 # print("int the bar...") # # def outer(func): # print("in the outer...") # func() # # outer(bar) #传递函数名为实参,没有修改被装饰函数的源代码
#返回函数名 def bar(): print("int the bar...") def outer(func): print("in the outer...") return func bar = outer(bar) bar() #返回函数名没有修改原函数的调用方式
-
- 嵌套函数:在一个函数体中使用def语句定义另一个函数称为嵌套函数,注意不是调用!
装饰器==高阶函数+嵌套函数:
- 利用高阶函数(传递函数名为参数的特性)把要被装饰的函数,传递给装饰器函数以添加新的功能,并且不改变被装饰函数的源代码!
- 利用高阶函数(返回函数名),没有修改被装饰函数的调用方式.
- 利用嵌套函数把装饰器封装成一个函数,借助语法糖@调用。
''' 利用装饰器打印出函数的执行时间 ''' import time def timmer(func): def wrapper(): start_time = time.time() func() stop_time = time.time() print("The func.__name__ running %s second" % (stop_time-start_time)) return wrapper @timmer #装饰器的语法糖,这句等价于test1 = timmer(test1) def test1(): time.sleep(1) @timmer def test2(): #装饰器的语法糖,这句等价于test2 = timmer(test2), time.sleep(2) test1() #原函数的源代码和调用方式均没有改变 test2()
上面的原函数及装饰器均没有参数,带参数的装饰器:
''' 利用装饰器打印出函数的执行时间 ''' import time def timmer(func): def wrapper(*args,**kwargs): #被装饰函数的参数是传递给wrapper的,因此wrapper函数需要能接收参数 start_time = time.time() func(*args,**kwargs) stop_time = time.time() print("The %s running %s second" % (func.__name__,stop_time-start_time)) return wrapper @timmer #装饰器的语法糖,这句等价于test = timmer(test1) def test1(name): print (name.center(50,"-")) time.sleep(1) @timmer def test2(name): #装饰器的语法糖,这句等价于test = timmer(test2), print(name.center(50,"-")) time.sleep(2) test1("LFY") #原函数的源代码和调用方式均没有改变 test2("WXZ")
有一个需求,对于不同的被装饰函数,根据传入的参数不同,添加不同的功能!
两种方法:
- 再写一个装饰器(不推荐)。
- 第二种方法根据参数的不同,选择不同的装饰器。
对于test1函数和test2函数上面的装饰器,都添加显示执行时间的功能;现在有如下需求:对于test1不变,仍然添加函数执行时间的功能,对于test2函数添加打印出函数的开始执行时间和结束的时间。
# *-*coding:utf-8 *-* # Auth: wangxz import time def timmer(type): #就是在装饰器的外层在嵌套一个函数 def out_wrapper(func): def wrapper(*args, **kwargs): if type == "one": start_time = time.time() func(*args, **kwargs) stop_time = time.time() print("The %s running %s second" % (func.__name__, stop_time - start_time)) elif type == "two": print("The %s runging start at %s" % (func.__name__, time.time())) func(*args, **kwargs) print("The %s runging staop at %s" % (func.__name__, time.time())) return wrapper return out_wrapper @timmer("one") ##注意的是这个实参,传递给了那个形参 def test1(name): print (name.center(50,"-")) time.sleep(1) @timmer("two") # def test2(name): #装饰器的语法糖,这句等价于test = timmer(test2), print(name.center(50,"-")) time.sleep(2) test1("WXZ") #根据传递的语法糖的参数不同,选择不同的装饰器 test2("LFY") #
这段函数代码的执行结果如下:
#代码执行的结果如下: -----------------------WXZ------------------------ The test1 running 1.0000572204589844 second The test2 runging start at 1524373351.098816 -----------------------LFY------------------------ The test2 runging staop at 1524373353.0989301 Process finished with exit code 0
需要注意的是:
如果被装饰的函数有return返回值,那么在装饰器的wrapper()函数中,也需要使用return语句返回函数的结果。
---恢复内容结束---