12.装饰器

装饰器的形成过程

import time

def timmer(f):    #装饰器函数
    def inner():
        start=time.time()
        f()    #被装饰的函数
        end=time.time()
        print(start-end)
    return inner

def func():
    time.sleep(0.1)
    print('老板同时大家好')
func=timmer(func)
func()

f是一个局部变量,在函数timmer()执行完成后就会消失,但是被函数inner()引用,这里就形成一个闭包,因此装饰器的本质就是闭包函数

在以上代码中func=timmer(func)  ,由于函数timmer()返回值是inner,所以等价于func=inner ,最后func()就等价于inner(),相当于直接执行了函数inner()

而函数inner()中包含func()函数和其他语句,就相当于对函数func()的功能进行拓展,对函数func进行修饰。

以上代码也可以写成

import time

def timmer(f):    #装饰器函数
    def inner():
        start=time.time()
        f()    #被装饰的函数
        end=time.time()
        print(start-end)
    return inner

@timmer   
def func():
    time.sleep(0.1)
    print('老板同时大家好')

func()

这里是装饰器函数的正常写用方法,函数timmer是装饰器函数,对函数func()有装饰作用,使用装饰器是被写成@timmer   ,给被装饰的函数的加上这个,函数等价于func=timmer(func),通常的写法是@+装饰器函数名,同时这种类似的使用方法被称为语法糖,可以简化代码,方便使用

函数f()是被装饰的函数,这段代码中也就是函数func()。

装饰器的作用

不想修改函数的内容和调用方式,在原来的函数前后添加功能

装饰器遵循的原则

开放封闭原则

开放:对拓展是开放的

封闭:对修改是封闭的

带参数和返回值的装饰器函数

import time

def timmer(f):    #装饰器函数
    def inner(*args,**kwargs):
        start=time.time()
        ret = f(*args,**kwargs)    #被装饰的函数
        end=time.time()
        print(start-end)
        return ret
    return inner
@timmer
def func(a,b):
    time.sleep(0.1)
    print('老板同时大家好',a,b)
    return '新年好'
@timmer
def func1(a,b=1):
    time.sleep(0.1)
    print('老板同时大家好',a,b)
    return '新年好'
func()
func1()

如上代码,不确定装饰器函数的参数类型和数量时,可以使用动态参数*args和**kwargs

同时,功能函数几乎都是有返回值的,应该在装饰器函数内接受被装饰函数的返回值并返回。

装饰器的固定模式(必背)

def timmer(f):    #装饰器函数,f是被装饰的函数
    def inner(*args,**kwargs):
        ‘在被装饰函数之前要做的事’
        ret = f(*args,**kwargs)    #被装饰的函数,ret接受函数f的返回值
        ‘在被装饰函数之后要做的事’
        return ret
    return inner

@timmer    不使用该方法的话,可以使用  func=timmer(func) 代替该语法
def func():
print("hello")
return 'a'
ret=func() #表面上是使用func(),但是在使用装饰器函数后,实际上是在使用内部函数inner
#ret 接受函数func()的返回值

 

posted @ 2020-09-26 12:11  maday  阅读(59)  评论(0)    收藏  举报