1、装饰器介绍:

装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何改变的前提下,增加一些额外的功能,而装饰器的返回值也是一个函数对象。

2、装饰器遵循的原则:

(1) 不修改被装饰函数的原代码。

(2) 不修改被装饰函数的调用方式。

 

写代码要遵循开发封闭原则,虽然在这个原则是用面向对象开发的,但是也适用于函数式编程,简单来说,它规定已经实现功能的代码不允许被修改,但是可以被扩展,即:

封闭:已经实现功能的代码块

开放:对扩展功能的开发

3、装饰器的实现方法:

(1)装饰器固定格式:

def wrappers(fun):
    def inner(*args,**kwargs):
        """被装饰函数执行前的操作"""
        ret = fun(*args,**kwargs)
        """被装饰函数执行后的操作"""
        return ret
    return inner

(2)无参装饰器:

示例:

import time
def wrappers(fun):
    def inner(*args,**kwargs):
        start_time = time.time()
        ret = fun(*args,**kwargs)
        end_time = time.time()
        print('此函数执行时间为%s'%(end_time - start_time))
        return ret
    return inner

@wrappers     #这样的写法被称为语法糖
def func1():   #这个函数为打印99乘法表
    for i in range(1,10):
        for n in range(1,10):
            print(i,'x',n,"=",n*i,'\t',end='')
            if i == n:
                print('')
                break
func1()   #执行函数
测试一个函数的执行时间

结果:

(3) 有参装饰器:

示例:

 1 import time
 2 def timmer(a):   #在原来的基础上的外面再套一层函数
 3     def  wrappers(f):
 4         def inner(*args,**kwargs):
 5             if a:
 6                 start = time.time()
 7                 ret = f(*args,**kwargs)
 8                 stop = time.time()
 9                 print(stop - start)
10             else:
11                 ret = f(*args, **kwargs)
12             return ret
13         return inner
14     return wrappers
15 
16 flag = True    #定义一个标志位,如果是True的话,则被装饰的函数全部执行,如果是False的话,则所以被装饰的函数都不
17 
18 @timmer(flag)   #执行时:
19 1、@和timmer(flag)会分开执行,先执行timmer(flag),然后返回一个wrappers.
20 2、接下来在结合@和wrappers执行,执行的就是一个原本的装饰器了
21 def reg1():
22     time.sleep(0.245)
23     print('很复杂。。。')
24 
25 @timmer(flag)
26 def reg2():
27     time.sleep(0.245)
28     print('特别复杂。。。')
29 
30 @timmer(flag)
31 def reg3():
32     time.sleep(0.245)
33     print('非常复杂。。。')
34 reg1()
35 reg2()
36 reg3()
可以同时控制n多个函数的调用

(4) 多个装饰器装饰一个函数:

示例:

多个装饰器的执行顺序解析

4、函数信息__doc__和__name__使用:

(1) __doc__的使用:

a、不加载wraps模块的结果:(显示出来的是装饰器的解释信息)
 1 def wrappers(f):
 2     def inner1(*args,**kwargs):
 3         """装饰器解释信息"""
 4         print('函数运行前func1')
 5         ret = f(*args,**kwargs)
 6         print('函数运行后func1')
 7         return ret
 8     return inner1
 9 
10 @wrappers
11 def func1():
12     """被装饰函数的解释信息"""
13     print('正在运行此函数')
14 
15 print(func1.__doc__)
不加载wraps模块

结果:

b、加载wraps模块的结果:(结果读取的是被装饰的函数的解释信息)
 1 from functools import wraps
 2 def wrappers(f):
 3     @wraps(f)
 4     def inner1(*args,**kwargs):
 5         '''装饰器解释信息'''
 6         print('函数运行前func1')
 7         ret = f(*args,**kwargs)
 8         print('函数运行后func1')
 9         return ret
10     return inner1
11 
12 @wrappers
13 def func1():
14     """被装饰函数的解释信息"""
15     print('正在运行此函数')
16 
17 print(func1.__doc__)
加载wraps模块

结果:

(2) __name__的使用:(显示真正执行的函数的名字)

 1 def wrappers(f):  #f = func1
 2     def inner1(*args,**kwargs):
 3         '''装饰器解释信息'''
 4         print('函数运行前func1')
 5         ret = f(*args,**kwargs)  #f() = func1()
 6         print('函数运行后func1')
 7         return ret
 8     return inner1
 9 
10 @wrappers  #func1 = wrappers(func1),外部的func1等于inner1
11 def func1():
12     """被装饰函数的解释信息"""
13     print('正在运行此函数')
14 
15 func1()  #func1() = inner1()
16 
17 print(func1.__name__)  ##值为inner1
View Code

结果:

 

 

 

 

 

 

 

posted on 2018-06-04 14:35  花豆豆  阅读(131)  评论(0编辑  收藏  举报