装饰器函数1

装饰器函数

锲子

  1、写一个func1函数

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

 

  2、计算func1函数的时间(通过修改函数)

import time
def func1():
    start = time.time()
    print('in func1')
    print(time.time() - start)

func1()

 

  3、计算func1函数的时间(通过写时间函数计算一)

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

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


def func2():
    print('in func2')

timer(func1)
timer(func2)

 

  4、3、计算func1函数的时间(通过写时间函数计算二)

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

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

func1 =timer  #要是能这样的就完美了。。。可惜报错

 

  缺点:上面这段代码是会报错的,因为timer方法需要传递一个func参数,我们不能在赋值的时候传参,因为只要执行func1 = timer(func1),timer方法就直接执行了,下面的那句func1根本就没有意义。

装饰器的形成过程

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()
装饰器——简单版1

 

  缺点:执行函数时,需要做一次赋值调用

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()
装饰器语法糖

 

  小结:

    1、装饰器的本质:一个闭包函数

    2、装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

    3、疑惑解答,关于闭包函数加功能和直接使用函数加新功能,以及装饰器的执行过程详解

#闭包实现装饰器
import time
a =1
def func(a): #主功能
    print(a)
def wrapper(func):
    def inner(a):
        start = time.time()
        func(a)
        end =time.time()
        print(end - start)
    return inner
func = wrapper(func)
func(a)
#写一层函数直接实现增加功能
a=1
def func(a): #主功能
    print(a)

def wrapper(func):
    print('这是一个新功能')
    return func
func =wrapper(func)
func(a)
二者的区别:闭包实现装饰器可传入参数,写一层函数直接实现增加功能,不能传入参数,func =wrapper(func)这一步的时候新功能已执行,而闭包是func(a)时执行新功能
装饰器解疑惑

 

 

  带一个参数的装饰器的函数

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'))

装饰器——成功hold住所有函数传参
装饰器——带多个参数

  那个装饰器已经非常完美了,但是正常我们情况下查看函数的一些信息的方法在此处都会失效

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__)
装饰器——wraps demo

开放封闭原则

  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):
        ret =  func(*args,**kwargs)
        return ret
    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 @ 2019-03-17 16:48  与凯学习  阅读(137)  评论(0)    收藏  举报