python基础8(装饰器)

1、装饰器本质

装饰器的本质:一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

2、装饰器函数

假设要写一个输出函数执行时间的装饰器
def timer(func):
    def inner():
        start = time.time()    #这里需要导入time模块
        func()
        end = time.time()
        print(end - start)

def func():
    time.sleep(2)    #延长函数的执行时间,方便观察
    print('----')

func = timer(func)
func()  #实质是已经变成了inner函数

3、语法糖

如果按2写,每次都要写func = timer(func),并且比较不方便,这时候可以使用@语法来进行装饰

#timer和func函数还是按照2中的
@timer
def func():...  

#@timer其实就是相当于执行了func = timer(func)

4、装饰有返回值的函数的装饰器

有时候函数是有返回值的,我们就可以这么做

def timer(func):
    def inner():
        start = time.time()
        ret = func()    #通过赋值给ret来接收func函数的返回值
        end = time.time()
        print(end-start)
        return ret    #因为装饰完的函数其实就是inner函数,所以通过inner的return,就可以将func函数的返回值返回回去
    return inner

@timer
def func():
    time.sleep(1)
    print('hahaha')
    return 'oh,hsr'

ret = func()

5、装饰带参数的函数的装饰器

#要装饰带有参数的函数,只要在内层函数中加上对应的参数就行
def timer(func):
    def inner(args):
        start = time.time()
        func() 
        end = time.time()
        print(args,end-start)
    return inner

@timer
def func(args):
    time.sleep(1)
    print('hahaha')

func('aaa')

6、固定形式

# 在固定的形式中,我们使用带返回值的,并且不定参数

def wrapper(func):
    def inner(*args,**kwargs):    #这样就可以接收各种参数
        #运行被装饰函数之前要做的事
        ret = func(*args,**kwargs)
        #运行被装饰函数之后要做的事
        return ret
    return inner

7、wraps

使用装饰器后,如果我们打印被装饰函数的__name__将会变成装饰器内层函数的名字

@wrapper
def func():
    pass

print(func.__name__)    #打印inner

如果要让它变成的原来的,可以在内层函数的上方加上@wraps(func),需要导入functools模块

from functools import wraps
def wrapper(func):
    @wraps(func)
    def inner(*args,**kwargs):    #这样就可以接收各种参数
        #运行被装饰函数之前要做的事
        ret = func(*args,**kwargs)
        #运行被装饰函数之后要做的事
        return ret
    return inner

8、带参数的装饰器

如果要使用带参数的装饰器,可以在装饰器函数外面再套一层函数,并把要给装饰器的参数给最外层函数
def wrapper(flag):
    def wrapper_inner(func):
        @wraps(func)
        def inner(*args,**kwargs):    #这样就可以接收各种参数
            #运行被装饰函数之前要做的事
            ret = func(*args,**kwargs)
            #运行被装饰函数之后要做的事
            return ret
        return inner    

@wrapper(FLAG)
def func():
    pass

9、多个装饰器装饰一个函数

多个装饰器装饰一个函数的时候,会先从离函数最近的装饰器开始执行

def wrapper1(func):
    def inner():
        print("---1---")
        func()
        print("---1---")
    return inner

def wrapper2(func):
    def inner():
        print("---2---")
        func()
        print("---2---")
    return inner

@wrapper2
@wrapper1
def func():
    print("func")

func()
#结果
---2---
---1---
func
---1---
---2---

我们来看一下执行顺序

10、原则

开放封闭原则
开放:对扩展是开放的
封闭:对修改时封闭的

 

posted @ 2019-02-14 16:53  WaltHwang  阅读(171)  评论(0编辑  收藏  举报