python中装饰器使用

装饰器是对已有的模块进行装饰(添加新功能)的函数。

现有一段代码:

1 import time
2 def func1():
3     time.sleep(3)
4     print("in the func1")
5 def func2():
6     time.sleep(2)
7     print("in the func2")
8 func1()
9 func2()

现在需要增加func1和func2的功能,计算段代码的运行时间。

思路1:修改函数内的代码:

 1 import time
 2 def func1():
 3     start_time = time.time()
 4     time.sleep(3)
 5     print("in the func1")
 6     stop_time = time.time()
 7     print("this program run %ss"%(stop_time-start_time))
 8 def func2():
 9     start_time = time.time()
10     time.sleep(2)
11     print("in the func2")
12     stop_time = time.time()
13     print("this program run %ss"%(stop_time-start_time))
14 func1()
15 func2()

每个函数都添加了红色的代码段,如果需要改的func较多时,该方法明显不适用。并且违反了为函数添加附加功能时的原则1:不能修改被装饰函数的源代码。

思路2:增加新函数:

 1 import time
 2 def func1():
 3     time.sleep(3)
 4     print("in the func1")
 5 def func2():
 6     time.sleep(2)
 7     print("in the func2")
 8 def func_new1():
 9     start_time = time.time()
10     func1()
11     stop_time =time.time()
12     print("this program run %ss"%(stop_time-start_time))
13 def func_new2():
14     start_time = time.time()
15     func2()
16     stop_time =time.time()
17     print("this program run %ss"%(stop_time-start_time))
18 func_new1()
19 func_new2()

该方法增加了新函数,将原有函数引用至新函数中。但问题又来了,需要改主程序中对原有函数的引用方法,违反了并且违反了为函数添加附加功能时的原则2:不能修改被装饰函数的调用方式。

此刻,我们需要新的知识储备来完善对装饰器的理解

1.函数的嵌套

2.高阶函数

3.函数——变量的关系

高阶函数+嵌套函数===》装饰器

插入名词的解释!!

高阶函数:满足下列原则之一的就是高阶函数:

  a.把一个函数名当作实参传给另一个函数的函数。

 1 import time
 2 def bar():
 3     time.sleep(3)
 4     print("in the bar")
 5 def test(func):
 6     start_time = time.time()
 7     func()
 8     stop_time = time.time()
 9     print("the func run time is %s"%(stop_time-start_time))
10 test(bar)

在此函数中,bar作为实参被传递给形参func,test(bar)。通过test()函数为bar()增加了新功能,且没有改变bar()的源代码。但改变了原有bar()的调用方式。

实现了不修改被装饰函数的源代码情况下为其添加新功能的目的。

  b.返回值中包含函数名

 1 import time
 2 def bar():
 3     time.sleep(3)
 4     print("in the bar")
 5 def test(func):
 6     print(func)
 7     print()
 8     return func
 9 bar = test(bar)
10 bar()

在此代码中,原有函数bar(),然后bar作为函数名被传给新增函数test(),随后又作为该函数的返回值。相当与给bar()增加了新的功能(显示bar()的内存地址),但没有改变bar()的调用方式。

嵌套函数:在函数体内声明的函数(必须是声明,不能是调用)

def test1():
    print("in the test1")
    def test2():
        print("in the test2")
    test2()
test1()

test2()是在test1()中声明的函数

将高阶函数与嵌套函数结合,

 1 import time
 2 def timmer(func):
 3     def deco():
 4         start_time = time.time()
 5         func()
 6         stop_time = time.time()
 7         print("the func run time is %ss"%(stop_time-start_time))
 8     return deco
 9 @timmer    #等于在func1被调用前加上func1=timmer(func1)
10 def func1():
11     time.sleep(3)
12     print("in the func1")
13 @timmer
14 def func2():
15     time.sleep(2)
16     print("in the func2")
17 func1()
18 func2()

其中@timmer = func1= timmer(func1),就是在被装饰的函数前加上装饰器的名称。在没有改变被装饰代码的源代码及调用方式的情况下增加了其功能。

原文地址:https://www.cnblogs.com/yinsedeyinse/p/9893650.html