day 12 - 1 装饰器进阶

装饰器进阶

装饰器的简单回顾

装饰器
开发原则:开放封闭原则
装饰器的作用:在不改变原函数的调用方式的情况下,在函数的前后添加功能
装饰器的本质:闭包函数

装饰器的模式

def wrapper(func):
    def inner(*args,**kwargs):
        print("在被装饰的函数执行之前做的事")
        ret =func(*args,**kwargs)
        print("在被装饰的函数执行之前做的事")
        return ret
    return inner

@wrapper    #holiday = wrapper(holiday)
def holiday(day):
    print("放假休息 %s 天"%day)
    return '好开心'

ret = holiday(3)
print(ret)

 

我们来看两个双下方法:__name__ 、__doc__

def wahaha():
   '''
   一个打印娃哈哈的函数
   '''
   print('娃哈哈')

print(wahaha.__name__)  #查看字符串格式的函数名
print(wahaha.__doc__)     #document 显示函数的注释(限于多行注释)
#输出结果:
'''
wahaha

   一个打印娃哈哈的函数

'''

 

接下来是 wraps 函数

from functools import wraps  #引用 wraps 函数

def wrapper(func):
    #wraps() 加在最内层函数正上方
    #@wraps(func)   #在不使用 wraps 函数时 返回结果: inner  inner 函数的注释
    @wraps(func)    #使用 wraps 函数来装饰 inner 函数 返回结果:holiday  只是一个放假通知
    def inner(*args,**kwargs):
        '''
         inner 函数的注释
        '''
        print("在被装饰的函数执行之前做的事")
        ret =func(*args,**kwargs)
        print("在被装饰的函数执行之前做的事")
        return ret
    return inner

@wrapper    #holiday = wrapper(holiday)
def holiday(day):
    '''
    只是一个放假通知
    '''
    print("放假休息 %s 天"%day)
    return '好开心'

print(holiday.__name__)  #当不调用 wraps 函数时,显示的为 inner 函数的名称
print(holiday.__doc__)   #当不调用 wraps 函数时,显示的为 inner 函数的注释

ret = holiday(3)    #在使用装饰器 wraps 函数时,并不影响 holiday 函数的使用
print(ret)          #这正是装饰器函数的特点
# 返回结果:
'''
在被装饰的函数执行之前做的事
放假休息 3 天
在被装饰的函数执行之前做的事
好开心
'''

 

假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?
一个一个的取消掉? 没日没夜忙活3天。。。
过两天领导想通了,再让你加上。。。

#装饰器的三层嵌套 为的是给装饰器传入变量
import time
#flage = False  #此处控制执行与否
flage = True
def timmer_out(flag):
    def timmer(func):
        def inner(*args,**kwargs):
            if flage:
                start = time.time()
                ret = func(*args,**kwargs)
                end = time.time()
                print(end - start)
                return ret
            else:
                ret = func(*args,**kwargs)
                return ret
        return inner
    return timmer

@timmer_out(flage)  #timmer_out(flage) 表示 timmer_out(flage) == timmer
def func():         #@ 表示 @timmer 即:func == timmer(func)
    time.sleep(0.1)
    print("结束")

@timmer_out(flage)
def func2():
    time.sleep(0.1)
    print("结束")

func()
func2()

 

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

def wrapper(func):
    def inner(*args,**kwargs):
        print("-----1-----")
        ret = func(*args,**kwargs)
        print("*****1*****")
        return ret
    return inner

def wrapper2(func):
    def inner2(*args,**kwargs):
        print("-----2-----")
        ret = func(*args,**kwargs)
        print("*****2*****")
        return ret
    return inner2

def wrapper3(func):
    def inner3(*args,**kwargs):
        print("-----3-----")
        ret = func(*args,**kwargs)
        print("*****3*****")
        return ret
    return inner3

@wrapper3
@wrapper2
@wrapper
def f():
    print("in f")
    return '就是这样'
print(f())
输出结果如下:
-----3-----
-----2-----
-----1-----
in f
*****1*****
*****2*****
*****3*****
就是这样

 

执行过成可参考下图

 

Python类中的装饰器在当前类中的声明与调用

class Test():
    xx = False

    def __init__(self):
        pass

    def test(func):
        def wrapper(self, *args, **kwargs):
            # print(self.xx)
            return func(self, *args, **kwargs)

        return wrapper

    @test
    def test_a(self, a, b):
        print(f'ok,{a} {b}')    # ok,12 13


t = Test()
t.test_a(12, 13)

注意:

1. 其中装饰器test是在类Test中声明并在其方法test_a中调用

2. 装饰器test内层wrapper函数的首参数是self

参考资料:

1. Python decorators in classes

posted @ 2018-12-04 23:33  亦双弓  阅读(234)  评论(0编辑  收藏  举报