一,什么是装饰器?

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

装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景.

二,装饰器的形成过程.

现在我又一个需求我想躺你测试这个函数的执行时间,在不改变这个函数代码的情况下:

 

import time

def func1():
    print('in func1')

def timer(func):
    def inner():
        start = time.time()
        func()
        print(time.time() - start)
    return inner

func1 = timer(func1)
func1()

 

 

 

但是如果有多个函数,我都想让你测试他们的执行时间,你每次是不是都的func1=timer(func1)?

这样还是有点麻烦.因为这些函数的函数名可能是不相同,有func1,func2等等,

所以更简单的方法,python给你提供了,那就是语法糖

import time
def timer(func):
    def inner():
        start = time.time()
        func()
        print(time.time() - start)
    return inner

@timer   #==> func1 = timer(func1)
def func1():
    print('in func1')


func1()
View Code

 

刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办?

def timer(func):
    def inner(a):
        start = time.time()
        func(a)
        print(time.time() - start)
    return inner

@timer
def func1(a):
    print(a)

func1(1)
装饰器--带参数的装饰器
import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        print(time.time() - start)
        return re
    return inner

@timer   #==> func1 = timer(func1)
def func1(a,b):
    print('in func1')

@timer   #==> func2 = timer(func2)
def func2(a):
    print('in func2 and get a:%s'%(a))
    return 'fun2 over'

func1('aaaaaa','bbbbbb')
print(func2('aaaaaa'))
装饰器--无敌的接受所有的

上面的装饰器已经非常完美了,但是我们正常情况下查看函数信息的方法在此处都会丢失效果:

def index():
    '''这是一个主页信息'''
    print('from index')

print(index.__doc__)    #查看函数注释的方法
print(index.__name__)   #查看函数名的方法

  如何解决呢?

from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

@deco
def index():
    '''哈哈哈哈'''
    print('from index')

print(index.__doc__)
print(index.__name__)

三,开放封闭原则.

  1.对扩展是开放的

    为什么要对扩展开放呢?

    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何

  更信和修改.所以我们必须允许代码扩展,添加新功能.

  2.对修改是封闭的

    为什么要对修改封闭呢?

     就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给他人舒勇了,

  如果这个时候我们对其进行修改,很有可能影响其他已经在使用的该函数的用户.

  装饰器完美的遵循的这个开放封闭原则.

四.装饰器的主要功能个固定结构.

def timer(func):
    def inner(*args,**kwargs):
        '''执行函数之前要做的'''
        re = func(*args,**kwargs)
        '''执行函数之后要做的'''
        return re
    return inner
装饰器--固定格式
from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper
装饰器--固定格式-wraps版

五.带参数的装饰器.

  假如你有成千上万个函数使用一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?

  一个一个取消掉?,没日没夜忙活3天...

  过两天你领导想通了再让你加上...

def outer(flag):
    def timer(func):
        def inner(*args,**kwargs):
            if flag:
                print('''执行函数之前要做的''')
            re = func(*args,**kwargs)
            if flag:
                print('''执行函数之后要做的''')
            return re
        return inner
    return timer

@outer(False)
def func():
    print(111)

func()
带参数的装饰器

六,多个装饰器装饰一个函数.

def wrapper1(func):
    def inner():
        print('wrapper1 ,before func')
        func()
        print('wrapper1 ,after func')
    return inner

def wrapper2(func):
    def inner():
        print('wrapper2 ,before func')
        func()
        print('wrapper2 ,after func')
    return inner

@wrapper2
@wrapper1
def f():
    print('in f')

f()
多个装饰一个函数

 

posted on 2018-06-22 21:54  PiuPiudada  阅读(203)  评论(0编辑  收藏  举报