装饰器函数

导读目录:

1、装饰器的形成过程

  1.1  带返回值的装饰器(被装饰函数不带参)

  1.2 带参数的装饰器(进阶)

  1.3 装饰带参函数的装饰器

  1.4 多个装饰器装饰一个函数(进阶)

  1.5 查看函数信息的一些方法

  1.6 装饰器的固定模式demo

2、开放封闭原则

1、装饰器

 装饰器的作用:不想修改函数(func)的调用方式,但是还想在原来的函数前后添加功能。

  1.1  带返回值的装饰器(被装饰函数不带参)

import time
#### 功能体,通过函数闭包
def timer(f):   # 装饰器函数
    def inner():
        start = time.time()
        ret = f()     #被装饰的函数,ret = '新年好'
        end = time.time()
        print(end - start)
        return ret
    return inner     # 千万别加(),这里返回函数名【地址】,因为inner()没有返回值(None)

@timer         #语法糖:@装饰器函数名
def func():    # 被装饰的函数  <=> func = timer(func) = inner
    time.sleep(0.1)
    print('程序运行时间如下:')
    return '新年好'

ret = func()      # <=> ret = inner(),return '新年好'
print(ret)

运行结果:
程序运行时间如下:
0.10062098503112793
新年好

  1.2 带参数的装饰器(进阶)

import time
# FLAG = False
FLAG = True       #True的时候,执行装饰器函数
def timmer_out(flag):        #三层装饰器函数
    def timmer(func):
        def inner(*args,**kwargs):
            if flag:    #flag = True:计算函数执行的时间
                start = time.time()
                ret = func(*args,**kwargs)
                end = time.time()
                print(end - start)
                return ret
            else:    #flag = False:返回被装饰的函数
                ret = func(*args, **kwargs)
        return inner
    return timmer

@timmer_out(FLAG)  # 先调用timerout(FLAG)函数,return timmer;再作为timmer装饰器
def wahaha():      # timerout(FLAG)=timmer,@timmer ==> wahaha = timmer(wahaha) = inner
    time.sleep(0.1)
    print('wahaha函数运行时间:')

# timmer = timmer_out(FLAG)
@timmer_out(FLAG)
def erguotou():
    time.sleep(0.1)
    print('erguotou函数运行时间:')

wahaha()
erguotou()

# 运行结果:
wahaha函数运行时间:
0.10001826286315918
erguotou函数运行时间:
0.1002960205078125

  1.3 装饰带参函数的装饰器

import time

def timer(f):
    def inner(*args,**kwargs):
        start = time.time()
        ret = f(*args,**kwargs)    #func(2,b='5')  ret='新年好'
        end = time.time()
        print(end - start)
        return ret
    return inner

@timer       #  func = timer(func) = inner
def func(a,b):    # 被装饰的函数
    time.sleep(0.1)
    print('程序运行时间如下:',a,b)
    return '新年好'

ret = func(2,b='5')   # 执行inner(2,b='5')
print(ret)

#运行结果:
程序运行时间如下: 2 5
0.10095524787902832
新年好

  1.4 多个装饰器装饰一个函数(进阶)

def wrapper1(func):
    def inner1():
        print('wrapper1,before func')
        ret = func()   #f   ret = '哈哈哈'
        print('wrapper1,after func')
        return ret  
    return inner1

def wrapper2(func):
    def inner2():
        print('wrapper2,before func')
        ret = func()      #inner1()
        print('wrapper2,after func')
        return ret
    return inner2

def wrapper3(func):
    def inner3():
        print('wrapper3,before func')
        ret = func()      #inner2()
        print('wrapper3,after func')
        return ret
    return inner3

@wrapper3     #f = wrapper3(f) = wrapper3(inner2) = inner3
@wrapper2     #f = wrapper2(f) = wrapper2(inner1) = inner2
@wrapper1     #f = wrapper1(f) = inner1  【函数f()先找最近的装饰器wrapper1】
def f():
    print('in f')
    return '哈哈哈'
print(f())

运行结果:
wrapper3,before func
wrapper2,before func
wrapper1,before func
in f
wrapper1,after func
wrapper2,after func
wrapper3,after func
哈哈哈

  1.5 查看函数信息的一些方法

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

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

  1.6 装饰器的固定模式demo

import time

def wrapper(f):   # 装饰器函数
    def inner(*args, **kwargs):
        '''在被装饰的函数之前要做的事儿'''
        ret = f(*args,**kwargs)     #执行func()
        '''在被装饰的函数之后要做的事儿'''
        return ret
    return inner    # 千万别加(),这里返回函数名【地址】,因为inner()没有返回值(None)

@wrapper       # 语法糖:@装饰器函数名
def func():    # 被装饰的函数
    time.sleep(0.1)
    print('程序运行时间如下:')
    return '新年好'

ret = func()
print(ret)

2、开放封闭原则

# 1.对扩展是开放的

  为什么要对扩展开放呢?

  任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

# 2.对修改是封闭的

  为什么要对修改封闭呢?

  因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

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

 

posted @ 2019-04-10 12:27  timetellu  阅读(201)  评论(0编辑  收藏  举报